[LeetCode] 46. Permutations
LeetCode - 46. Permutations 알고리즘 문제 풀이
분류
문제 링크 : https://leetcode.com/problems/permutations/
풀이
nums
에 있는 수를 이용하여 만들 수 있는 순열을 구하는 문제이다. nums
의 모든 원소는 고유하고 문제 조건에 의해 nums.length의 최대 길이가 6이므로 원소를 뽑은 위치를 나타내기 위한 체크 배열을 이용하고, 뽑을 위치는 인덱스 i
에 해당하므로 idx 위치에 i를 저장하였다.
재귀의 기저 조건(N == idx)에 도달했을 때 임의의 정수 벡터 sub
를 생성하고 sub[i] = nums[idxArr[i]]
를 해주면 기저에 도달하기 이전까지 선택했던 인덱스 위치의 원소를 뽑을 수 있다.
핵심 코드는 아래의 부분이다.
- 아직 선택하지 않은 인덱스(
!useChk[i]
)인지 확인하고 선택하지 않은 경우에만 수행한다. i
위치를 선택했다고 true로 표시한 후, 뽑은 인덱스를 순서대로 저장한다. (idxArr[idx] = i
)- 재귀 호출을 하며, 이때 다음의 인덱스가 저장될 위치는
idx + 1
이므로idx + 1
을 매개변수로 전달한다. - 재귀 호출이 끝나고 되돌아오면
i
위치를 선택하지 않았다고 표시한다. (useChk[i] = false
)
for (int i = 0; i < N; ++i) {
if (!useChk[i]) {
useChk[i] = true;
idxArr[idx] = i;
perm(N, nums, result, idx + 1);
useChk[i] = false;
}
}
소스 코드
class Solution {
bool useChk[6];
int idxArr[6];
void perm(const int N, const vector<int>& nums,
vector<vector<int>>& result, int idx) {
if (N == idx) {
vector<int> sub(N);
for (int i = 0; i < N; ++i) {
sub[i] = nums[idxArr[i]];
}
result.push_back(move(sub));
return;
}
for (int i = 0; i < N; ++i) {
if (!useChk[i]) {
useChk[i] = true;
idxArr[idx] = i;
perm(N, nums, result, idx + 1);
useChk[i] = false;
}
}
}
public:
vector<vector<int>> permute(vector<int>& nums) {
const int N = (int)nums.size();
vector<vector<int>> result;
fill(useChk, useChk + N, false);
perm(N, nums, result, 0);
return result;
}
};
이 문제는 nums의 길이가 6이라 어느 방식으로 구현해도 큰 차이는 없을 것 같지만, swap을 사용하면 i를 0부터 시작하여 이미 사용하고 있는 위치를 몇 번씩 더 확인해야 할 필요으므로 인덱스를 일일이 검사하고 선택하는 것보다 빠를 것 같다. (마침 문제 조건에도 결과값 배열은 임의의 순서로 이루어져도 된다고 한다.) 만약 nums 배열이 오름차순으로 정렬되어 있고 순열을 순서대로(사전순으로) 생성해야 한다면 지금 작성한 코드가 좀 더 나을 것 같다.