Skip to content

Commit 622cfdb

Browse files
committed
add Next Permutation
1 parent 6dd0c7c commit 622cfdb

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed

SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
* [Permutation](exhaustive_search/permutation.md)
112112
* [Unique Permutations](exhaustive_search/unique_permutations.md)
113113
* [Unique Binary Search Trees II](exhaustive_search/unique_binary_search_trees_ii.md)
114+
* [Next Permutation](exhaustive_search/next_permutation.md)
114115
* [Dynamic Programming - 动态规划](dynamic_programming/README.md)
115116
* [Triangle](dynamic_programming/triangle.md)
116117
* [Knapsack - 背包问题](dynamic_programming/knapsack.md)

exhaustive_search/next_permutation.md

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
# Next Permutation
2+
3+
## Source
4+
5+
- lintcode: [(52) Next Permutation](http://www.lintcode.com/en/problem/next-permutation/)
6+
7+
```
8+
Given a list of integers, which denote a permutation.
9+
10+
Find the next permutation in ascending order.
11+
12+
Example
13+
For [1,3,2,3], the next permutation is [1,3,3,2]
14+
15+
For [4,3,2,1], the next permutation is [1,2,3,4]
16+
17+
Note
18+
The list may contains duplicate integers.
19+
```
20+
21+
## 题解
22+
23+
找下一个升序排列,C++ STL 源码剖析一书中有提及,[Permutation](http://algorithm.yuanbin.me/exhaustive_search/permutation.html) 一小节中也有详细介绍,下面简要介绍一下字典序算法:
24+
25+
1. 从后往前寻找索引满足 `a[k] < a[k + 1]`, 如果此条件不满足,则说明已遍历到最后一个。
26+
2. 从后往前遍历,找到第一个比`a[k]`大的数`a[l]`, 即`a[k] < a[l]`.
27+
3. 交换`a[k]``a[l]`.
28+
4. 反转`k + 1 ~ n`之间的元素。
29+
30+
由于这道题中规定对于`[4,3,2,1]`, 输出为`[1,2,3,4]`, 故在第一步稍加处理即可。
31+
32+
### Python
33+
34+
```python
35+
class Solution:
36+
# @param num : a list of integer
37+
# @return : a list of integer
38+
def nextPermutation(self, num):
39+
if num is None or len(num) <= 1:
40+
return num
41+
# step1: find nums[i] < nums[i + 1], Loop backwards
42+
i = 0
43+
for i in xrange(len(num) - 2, -1, -1):
44+
if num[i] < num[i + 1]:
45+
break
46+
elif i == 0:
47+
# reverse nums if reach maximum
48+
num = num[::-1]
49+
return num
50+
# step2: find nums[i] < nums[j], Loop backwards
51+
j = 0
52+
for j in xrange(len(num) - 1, i, -1):
53+
if num[i] < num[j]:
54+
break
55+
# step3: swap betwenn nums[i] and nums[j]
56+
num[i], num[j] = num[j], num[i]
57+
# step4: reverse between [i + 1, n - 1]
58+
num[i + 1:len(num)] = num[len(num) - 1:i:-1]
59+
60+
return num
61+
```
62+
63+
### C++
64+
65+
```c++
66+
class Solution {
67+
public:
68+
/**
69+
* @param nums: An array of integers
70+
* @return: An array of integers that's next permuation
71+
*/
72+
vector<int> nextPermutation(vector<int> &nums) {
73+
if (nums.empty() || nums.size() <= 1) {
74+
return nums;
75+
}
76+
// step1: find nums[i] < nums[i + 1]
77+
int i = 0;
78+
for (i = nums.size() - 2; i >= 0; --i) {
79+
if (nums[i] < nums[i + 1]) {
80+
break;
81+
} else if (0 == i) {
82+
// reverse nums if reach maximum
83+
reverse(nums, 0, nums.size() - 1);
84+
return nums;
85+
}
86+
}
87+
// step2: find nums[i] < nums[j]
88+
int j = 0;
89+
for (j = nums.size() - 1; j > i; --j) {
90+
if (nums[i] < nums[j]) break;
91+
}
92+
// step3: swap betwenn nums[i] and nums[j]
93+
int temp = nums[i];
94+
nums[i] = nums[j];
95+
nums[j] = temp;
96+
// step4: reverse between [i + 1, n - 1]
97+
reverse(nums, i + 1, nums.size() - 1);
98+
99+
return nums;
100+
101+
}
102+
103+
private:
104+
void reverse(vector<int>& nums, int start, int end) {
105+
for (int i = start, j = end; i < j; ++i, --j) {
106+
int temp = nums[i];
107+
nums[i] = nums[j];
108+
nums[j] = temp;
109+
}
110+
}
111+
};
112+
```
113+
114+
### Java
115+
116+
```java
117+
public class Solution {
118+
/**
119+
* @param nums: an array of integers
120+
* @return: return nums in-place
121+
*/
122+
public int[] nextPermutation(int[] nums) {
123+
if (nums == null || nums.length <= 1) {
124+
return nums;
125+
}
126+
// step1: find nums[i] < nums[i + 1]
127+
int i = 0;
128+
for (i = nums.length - 2; i >= 0; i--) {
129+
if (nums[i] < nums[i + 1]) {
130+
break;
131+
} else if (i == 0) {
132+
// reverse nums if reach maximum
133+
reverse(nums, 0, nums.length - 1);
134+
return nums;
135+
}
136+
}
137+
// step2: find nums[i] < nums[j]
138+
int j = 0;
139+
for (j = nums.length - 1; j > i; j--) {
140+
if (nums[i] < nums[j]) {
141+
break;
142+
}
143+
}
144+
// step3: swap betwenn nums[i] and nums[j]
145+
int temp = nums[i];
146+
nums[i] = nums[j];
147+
nums[j] = temp;
148+
// step4: reverse between [i + 1, n - 1]
149+
reverse(nums, i + 1, nums.length - 1);
150+
151+
return nums;
152+
}
153+
154+
private void reverse(int[] nums, int start, int end) {
155+
for (int i = start, j = end; i < j; i++, j--) {
156+
int temp = nums[i];
157+
nums[i] = nums[j];
158+
nums[j] = temp;
159+
}
160+
}
161+
}
162+
```
163+
164+
### 源码分析
165+
166+
和 Permutation 一小节类似,这里只需要注意在step 1中`i == 0`时需要反转之以获得最小的序列。对于有重复元素,只要在 step1和 step2中判断元素大小时不取等号即可。
167+
168+
### 复杂度分析
169+
170+
最坏情况下,遍历两次原数组,反转一次数组,时间复杂度为 $$O(n)$$, 使用了 temp 临时变量,空间复杂度可认为是 $$O(1)$$.
171+
172+
## Reference
173+
174+
- [Permutation | Data Structure and Algorithm](http://algorithm.yuanbin.me/exhaustive_search/permutation.html)

0 commit comments

Comments
 (0)