코딩 테스트/알고리즘 공부
중복순열(DFS 깊이우선탐색)
fullfish
2022. 4. 26. 01:07
맨 아래에 다듬은 수정 코드 업데이트(배열 주어졌을때랑 안주어졌을때랑 조금 달라서 같은 느낌으로 통일시킴)
1부터 n까지의 숫자중
m개를 중복순열한다면
function permutationWithRepetition(n, m) {
let arr = new Array(m).fill(0);
// let arr = Array.from({ length: m }, () => 0); // 이렇게 해도 됨
let answer = [];
function DFS(L) {
if (L === m) {
answer.push(arr.slice());
} else {
for (let i = 1; i <= n; i++) {
arr[L] = i;
DFS(L + 1);
}
}
}
DFS(0);
return answer;
}
console.log(permutationWithRepetition(3, 3));
//결과
[
[ 1, 1, 1 ], [ 1, 1, 2 ], [ 1, 1, 3 ],
[ 1, 2, 1 ], [ 1, 2, 2 ], [ 1, 2, 3 ],
[ 1, 3, 1 ], [ 1, 3, 2 ], [ 1, 3, 3 ],
[ 2, 1, 1 ], [ 2, 1, 2 ], [ 2, 1, 3 ],
[ 2, 2, 1 ], [ 2, 2, 2 ], [ 2, 2, 3 ],
[ 2, 3, 1 ], [ 2, 3, 2 ], [ 2, 3, 3 ],
[ 3, 1, 1 ], [ 3, 1, 2 ], [ 3, 1, 3 ],
[ 3, 2, 1 ], [ 3, 2, 2 ], [ 3, 2, 3 ],
[ 3, 3, 1 ], [ 3, 3, 2 ], [ 3, 3, 3 ]
]
재귀를 사용해서
DFS(0) 일때 arr[0] = 1
DFS(1) 일때 arr[1] = 1
DFS(2) 일때 arr[2] = 1
DFS(3) 일때 L===m 이므로 얕은 복사를 이용해서 [1,1,1]이 answer로 push되고 이런식으로 반복된다
예를들어 배열이 주어졌다면
let arr = ["rock", "scissors", "paper"];
function rockScissorsPaper(arr, n) {
let answer = [];
function DFS(L, S) {
if (L === 0) {
answer.push(S);
return;
}
for (let i = 0; i < arr.length; i++) {
DFS(L - 1, S.concat(arr[i])); //이건 중복 순열
// if (!S.includes(box[i])) DFS(L - 1, S.concat(box[i])); //이건 순열
}
}
DFS(n, []);
return answer;
}
console.log(rockScissorsPaper(arr,3))
//결과
[
[ 'rock', 'rock', 'rock' ],
[ 'rock', 'rock', 'scissors' ],
[ 'rock', 'rock', 'paper' ],
[ 'rock', 'scissors', 'rock' ],
[ 'rock', 'scissors', 'scissors' ],
[ 'rock', 'scissors', 'paper' ],
[ 'rock', 'paper', 'rock' ],
[ 'rock', 'paper', 'scissors' ],
[ 'rock', 'paper', 'paper' ],
[ 'scissors', 'rock', 'rock' ],
[ 'scissors', 'rock', 'scissors' ],
[ 'scissors', 'rock', 'paper' ],
[ 'scissors', 'scissors', 'rock' ],
[ 'scissors', 'scissors', 'scissors' ],
[ 'scissors', 'scissors', 'paper' ],
[ 'scissors', 'paper', 'rock' ],
[ 'scissors', 'paper', 'scissors' ],
[ 'scissors', 'paper', 'paper' ],
[ 'paper', 'rock', 'rock' ],
[ 'paper', 'rock', 'scissors' ],
[ 'paper', 'rock', 'paper' ],
[ 'paper', 'scissors', 'rock' ],
[ 'paper', 'scissors', 'scissors' ],
[ 'paper', 'scissors', 'paper' ],
[ 'paper', 'paper', 'rock' ],
[ 'paper', 'paper', 'scissors' ],
[ 'paper', 'paper', 'paper' ]
]
DFS(L - 1, S.concat(arr[i])); 이부분 push가 아닌 concat을 해준 이유는
push는 추가된 후 배열의 length값이 반환되기 때문이다.
수정된 코드
숫자 일떄
function solution(n) {
let result = []
let N = n
function DFS(n, tempArr) {
if (n === 0) return result.push(tempArr)
else {
for (let i = 1; i <= N; i++) {
DFS(n - 1, tempArr.concat(i)) // 중복순열
// if (!tempArr.includes(i)) DFS(n - 1, tempArr.concat(i)); // 순열
}
}
}
DFS(n, [])
return result
}
배열 주어 졌을 때
let arr = ['rock', 'scissors', 'paper']
function solution2(arr, n) {
let result = []
function DFS(n, tempArr) {
if (n === 0) return result.push(tempArr)
for (let i = 0; i < arr.length; i++) {
DFS(n - 1, tempArr.concat(arr[i])) // 중복 순열
// if (!tempArr.includes(arr[i])) DFS(n - 1, tempArr.concat(arr[i])); // 순열
}
}
DFS(n, [])
return result
}
concat(i) 대신에 concat(arr[i])로 바뀌고 for문이 0부터 시작한것만 변경됐다