Skip to content

Commit ab87771

Browse files
committed
31.下一个排列
1 parent af4263c commit ab87771

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

leetcode_Java/DoneTitle.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
20. 有效的括号
1111
21. 合并两个有序链表
1212
22. 括号生成
13+
31. 下一个排列
1314
37. 解数独
1415
39. 组合总和
1516
40. 组合总和 II

leetcode_Java/Solution0031.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// 31. 下一个排列
2+
3+
4+
/*
5+
1、“下一个排列”定义:
6+
1)给定数字序列的字典序中下一个更大的排列。可以理解成这些数字拼凑成的多个整数,升序排序,然后求当前整数的下一个整数
7+
2)如果不存在下一个更大的排列,则将数字重新排列成最小的排列。即整数是最大的,那么整体升序排列得到一个最小的整数
8+
2、算法推导
9+
1)我们希望下一个数比当前数大,这样才满足“下一个排列”的定义。因此只需要将后面的「大数」与前面的「小数」交换,就能得到一个更大的数
10+
2)我们还希望下一个数增加的幅度尽可能的小,这样才满足“下一个排列与当前排列紧邻“的要求。为了满足这个要求,需要:
11+
① 在尽可能靠右的低位进行交换,需要从后向前查找
12+
② 将一个尽可能小的「大数」与前面的「小数」交换
13+
③ 将「大数」换到前面后,需要将「大数」后面的所有数重置为升序,升序排列就是最小的排列
14+
3、算法过程
15+
1)从后向前查找第一个相邻升序的元素对 (i-1,i),满足 A[i-1] < A[i],即找到第一个可交换的最低位「小数」。此时 [i,end) 必然是降序
16+
2)在 [i,end) 从后向前查找第一个满足 A[i-1] < A[j] 的 j,即找到第一个可交换的值最小的「大数」。A[i-1]、A[j] 分别是「小数」、「大数」
17+
3)将 A[i-1] 与 A[j] 交换
18+
4)此时 [i,end) 必然是降序,逆置 [i,end),使其升序
19+
5)如果在步骤1找不到符合的相邻升序元素对,说明当前 [0,end) 为一个降序顺序,即最大的排序,则整体升序得到最小的排列
20+
21+
1 2 3 8 5 7 6 4
22+
↑ ↑ ↑
23+
i-1 i j
24+
1 2 3 8 6 4 5 7
25+
*/
26+
class Solution {
27+
public void nextPermutation(int[] nums) {
28+
int n = nums.length;
29+
if (n <= 1) {
30+
return;
31+
}
32+
for (int i = n - 1; i >= 1; i--) {
33+
if (nums[i] > nums[i - 1]) {
34+
for (int j = n - 1; j >= i; j--) {
35+
if (nums[j] > nums[i - 1]) {
36+
int temp = nums[j];
37+
nums[j] = nums[i - 1];
38+
nums[i - 1] = temp;
39+
Arrays.sort(nums, i, n);
40+
return;
41+
}
42+
}
43+
}
44+
}
45+
Arrays.sort(nums);
46+
}
47+
}

0 commit comments

Comments
 (0)