문제 설명#
Next Permutation - LeetCode
주어진 숫자 배열 nums
에 대해 사전순(lexicographically)으로 다음 순열을 찾는 문제입니다.
- 현재 순열보다 크면서 가장 작은 값이 되는 순열을 찾기
- 제자리(in-place)에서 변경해야 하며, 추가 배열을 사용하지 않아야 함
- 가장 큰 순열이면 가장 작은 순열로 변경 (예:
[3, 2, 1] → [1, 2, 3]
)
✅ 제약 조건:
- 1 ≤
nums.length
≤ 100 - 0 ≤
nums[i]
≤ 100
1️⃣ 브루트포스 (O(N!)) → 비효율적#
- 모든 순열을 생성한 후, 현재 순열 다음 값을 찾음
- 매우 비효율적 → 사용하지 않음
2️⃣ 최적화된 O(N) 풀이 (그리디 + 정렬) [추천]#
✔ 순열의 다음 값은 다음과 같은 과정으로 구할 수 있음
- 뒤에서부터 (오른쪽에서) 내림차순이 아닌 지점(
i
)을 찾기nums[i] < nums[i+1]
인 가장 큰 i
를 찾음- 이 값은 더 큰 숫자로 교체될 값
i
보다 오른쪽에서 nums[i]
보다 큰 숫자(j
)를 찾기nums[j] > nums[i]
인 가장 큰 j
찾기
nums[i]
와 nums[j]
를 swapi+1
부터 끝까지 오름차순 정렬- 가장 작은 다음 순열을 만들기 위해 정렬 (사실상 뒤집기)
코드 풀이#
Python#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| def nextPermutation(nums):
n = len(nums)
# Step 1: 뒤에서부터 내림차순이 아닌 첫 번째 위치 찾기
i = n - 2
while i >= 0 and nums[i] >= nums[i + 1]:
i -= 1
if i >= 0: # 내림차순이 아닌 위치가 있으면
# Step 2: nums[i]보다 큰 숫자를 뒤에서부터 찾기
j = n - 1
while nums[j] <= nums[i]:
j -= 1
# Step 3: Swap
nums[i], nums[j] = nums[j], nums[i]
# Step 4: i+1부터 끝까지 오름차순 정렬 (뒤집기)
nums[i + 1:] = reversed(nums[i + 1:])
|
Javascript#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| var nextPermutation = function(nums) {
let i = nums.length - 2;
// Step 1: 뒤에서부터 내림차순이 아닌 첫 번째 위치 찾기
while (i >= 0 && nums[i] >= nums[i + 1]) {
i--;
}
if (i >= 0) { // 내림차순이 아닌 위치가 있으면
let j = nums.length - 1;
// Step 2: nums[i]보다 큰 숫자를 뒤에서부터 찾기
while (nums[j] <= nums[i]) {
j--;
}
// Step 3: Swap
[nums[i], nums[j]] = [nums[j], nums[i]];
}
// Step 4: i+1부터 끝까지 오름차순 정렬 (뒤집기)
let left = i + 1, right = nums.length - 1;
while (left < right) {
[nums[left], nums[right]] = [nums[right], nums[left]];
left++;
right--;
}
};
|
참고 및 출처#
programmers Coding Test
LeetCode - The World’s Leading Online Programming Learning Platform