Skip to content

Commit 02352a9

Browse files
committed
add Previous Permutation
1 parent 622cfdb commit 02352a9

File tree

2 files changed

+171
-1
lines changed

2 files changed

+171
-1
lines changed

SUMMARY.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,9 @@
110110
* [Unique Subsets](exhaustive_search/unique_subsets.md)
111111
* [Permutation](exhaustive_search/permutation.md)
112112
* [Unique Permutations](exhaustive_search/unique_permutations.md)
113-
* [Unique Binary Search Trees II](exhaustive_search/unique_binary_search_trees_ii.md)
114113
* [Next Permutation](exhaustive_search/next_permutation.md)
114+
* [Previous Permuation](exhaustive_search/previous_permuation.md)
115+
* [Unique Binary Search Trees II](exhaustive_search/unique_binary_search_trees_ii.md)
115116
* [Dynamic Programming - 动态规划](dynamic_programming/README.md)
116117
* [Triangle](dynamic_programming/triangle.md)
117118
* [Knapsack - 背包问题](dynamic_programming/knapsack.md)
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
# Previous Permuation
2+
3+
## Source
4+
5+
- lintcode: [(51) Previous Permuation](http://www.lintcode.com/en/problem/previous-permuation/)
6+
7+
```
8+
Given a list of integers, which denote a permutation.
9+
10+
Find the previous permutation in ascending order.
11+
12+
Example
13+
For [1,3,2,3], the previous permutation is [1,2,3,3]
14+
15+
For [1,2,3,4], the previous permutation is [4,3,2,1]
16+
17+
Note
18+
The list may contains duplicate integers.
19+
```
20+
21+
## 题解
22+
23+
和前一题 [Next Permutation](http://algorithm.yuanbin.me/exhaustive_search/next_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+
为何不从前往后呢?因为只有从后往前才能保证得到的是相邻的排列,可以举个实际例子自行分析。
31+
32+
### Python
33+
34+
```python
35+
class Solution:
36+
# @param num : a list of integer
37+
# @return : a list of integer
38+
def previousPermuation(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 previous permuation
71+
*/
72+
vector<int> previousPermuation(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 minimum
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+
private:
103+
void reverse(vector<int>& nums, int start, int end) {
104+
for (int i = start, j = end; i < j; ++i, --j) {
105+
int temp = nums[i];
106+
nums[i] = nums[j];
107+
nums[j] = temp;
108+
}
109+
}
110+
};
111+
```
112+
113+
### Java
114+
115+
```java
116+
public class Solution {
117+
/**
118+
* @param nums: A list of integers
119+
* @return: A list of integers that's previous permuation
120+
*/
121+
public ArrayList<Integer> previousPermuation(ArrayList<Integer> nums) {
122+
if (nums == null || nums.size() <= 1) {
123+
return nums;
124+
}
125+
// step1: find nums[i] > nums[i + 1]
126+
int i = 0;
127+
for (i = nums.size() - 2; i >= 0; i--) {
128+
if (nums.get(i) > nums.get(i + 1)) {
129+
break;
130+
} else if (i == 0) {
131+
// reverse nums if reach minimum
132+
reverse(nums, 0, nums.size() - 1);
133+
return nums;
134+
}
135+
}
136+
// step2: find nums[i] > nums[j]
137+
int j = 0;
138+
for (j = nums.size() - 1; j > i; j--) {
139+
if (nums.get(i) > nums.get(j)) {
140+
break;
141+
}
142+
}
143+
// step3: swap betwenn nums[i] and nums[j]
144+
Collections.swap(nums, i, j);
145+
// step4: reverse between [i + 1, n - 1]
146+
reverse(nums, i + 1, nums.size() - 1);
147+
148+
return nums;
149+
}
150+
151+
private void reverse(List<Integer> nums, int start, int end) {
152+
for (int i = start, j = end; i < j; i++, j--) {
153+
Collections.swap(nums, i, j);
154+
}
155+
}
156+
}
157+
```
158+
159+
### 源码分析
160+
161+
和 Permutation 一小节类似,这里只需要注意在step 1中`i == 0`时需要反转之以获得最大的序列。对于有重复元素,只要在 step1和 step2中判断元素大小时不取等号即可。
162+
163+
### 复杂度分析
164+
165+
最坏情况下,遍历两次原数组,反转一次数组,时间复杂度为 $$O(n)$$, 使用了 temp 临时变量,空间复杂度可认为是 $$O(1)$$.
166+
167+
## Reference
168+
169+
- [Permutation | Data Structure and Algorithm](http://algorithm.yuanbin.me/exhaustive_search/permutation.html)

0 commit comments

Comments
 (0)