- 题目
- 思路
- 更简便做法
- 常用函数
整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。求比当前排列大的第一个排列。
思路整个数组是降序排列就是最大的排列,如[5,4,3,2,1]。
我们希望下一个数比当前数大,这样才满足“下一个排列”的定义。
- 因此只需要将后面的「大数」与前面的「小数」交换,就能得到一个更大的数。比如 123456,将 5 和 6 交换就能得到一个更大的数 123465。
- 我们还希望下一个数增加的幅度尽可能的小,这样才满足“下一个排列与当前排列紧邻“的要求。为了满足这个要求,我们需要:
*在尽可能靠右的低位进行交换,需要从后向前查找
*将一个 尽可能小的「大数」 与前面的「小数」交换。比如 123465,下一个排列应该把 5 和 4 交换而不是把 6 和 4 交换
*将「大数」换到前面后,需要将「大数」后面的所有数重置为升序,升序排列就是最小的排列。以 123465 为例:首先按照上一步,交换 5 和 4,得到 123564;然后需要将 5 之后的数重置为升序,得到 123546。显然 123546 比 123564 更小,123546 就是 123465 的下一个排列
算法思路
1.先从后往前找到一个降序的位置i,说明这个位置的值可以换一个更大的值从而使数变大。如果没找到,说明这个数组已经是最大的了,颠倒数组。
2.i之后的数从后往前看肯定使升序的,所以我们从后往前找第一个比i位置大的元素位置j,这个数就是比i大的最小的元素与i进行交换。
3.位置i之后的元素重新排序。
//实现的时候针对思路后面先排序后交换
class Solution {
public void nextPermutation(int[] nums) {
// 从后往前,找到前一位比当前位置小的(i-1 < i)
int len = nums.length;
for (int i = len - 1; i > 0; i--) {
//找到第一个可以变大的位置i-1
if (nums[i] > nums[i - 1]) {
// 将 [i] -> [length]
Arrays.sort(nums, i, len);
//从排好的序中找出一个比nums[i-1]大的数,说明这个数是比nums[i-1]大的最小的一个数,从而保证整体最小,而且nums[i-1]交换过去之后,i-1之后肯定是升序的
for (int j = i; j < len; j++) {
// 从左往右,在 4 6 7 中找到第一个 > nums[下标4] = 5
// 注意是 nums[i - 1] 是 i-1 ,不是 j !!!
if (nums[j] > nums[i - 1]) {
//交换位置,然后return
int temp = nums[j];
nums[j] = nums[i - 1];
nums[i - 1] = temp;
return;
}
}
}
//如果走一遍空循环,看下一行注释
}
// 上面循环完之后,程序还在运行说明 此排列已经最大
// 做一个升序排列就完事
Arrays.sort(nums);
}
}
更简便做法
next_permutation(tmp.begin(), tmp.end())
C++ STL全排列 next_permutation 用法
templatebool next_permutation (Iterator first, Iterator last); template bool next_permutation (Iterator first, Iterator last, Compare comp);
next_permutation是一个原地算法(会直接改变这个集合,而不是返回一个集合),它对一个可以遍历的集合(如string,如vector),将迭代器范围 [first, last]的下一个排列。其中所有排列的集合默认按照operator < 或者 字典序 或者 按照输入到第三个参数 compare的排列方法排列。如果存在这样的“下一个排列”,返回true并执行排列,否则返回false。
常用函数整数转字符串
to_string()
字符串转数组
stol()



