1 题目描述
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.
If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).
The replacement must be in-place, do not allocate extra memory.
难度:Medium
2 题目样例
Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3
→ 1,3,2
3,2,1
→ 1,2,3
1,1,5
→ 1,5,1
3 题意分析
给定一个排列,要求求出按照字典序排序的这个排列的下一个排列。也就是求出在原排列中只大于现排列的排列。
如果当前数字代表的整数值已经是所有排列组合中的最大值,则返回当前数字组成的最小值。
4 思路分析
本质就是一个找数学规律的题目,可以转化为各个位上的数字如何调整顺序才能生成一个最小的更大值的问题。而且我们还要尽可能的保证调整顺序的次数尽可能的小。
(我刚开始看到题设中的箭头还以为这题目和数据结构有什么关系呢……这可能就是数据结构恐惧症吧。)
首先我们要明确调整顺序的原则:可以将低位移到高位,只要低位的数字比高位上的数字大。但是,为了确保的到尽可能小的最大值,一定要将移动的位确保越小越好。其次,要保证移动之后,高位以后的值为最小值。
我们可以用一个例子来模拟整个过程,以期发现规律。
例如,对:
4,2,0,2,3,2,0
我们采取以下的步骤:
- 数组从后往前遍历
- 数字2比它后面的每一位都大,所以它换到哪一位上都比原来的数字小。
- 数字 3 同理。
- 数字 2 后面存在大于它的数字 3(3 是 大于 2 的数字中最小的),它们俩交换后能增大原本的数字。为了使增大的数字最小,要使 3 后的数字变为递增排列。
最后能够得到符合题意的序列为:
4,2,0,3,0,2,2
总结上述规律,可知普遍规律如下:
- 由最低位开始,由低往高遍历,找到可以进行替换的最小位。
- 可以替换的条件是,比当前位低的位上存在一个数,该数比当前位上的值大,且不存在另一个比该值小且比当前位上值大的数
- 替换数值后,该进行替换的位后序的位上的值应当保证为最小值。
代码实现如下:
class Solution {
public:
void nextPermutation(vector<int> &num) {
int i, j, n = num.size();
for (i = n - 2; i >= 0; --i) {
if (num[i + 1] > num[i]) {
for (j = n - 1; j > i; --j) {
if (num[j] > num[i]) break;
}
swap(num[i], num[j]);
reverse(num.begin() + i + 1, num.end());
return;
}
}
reverse(num.begin(), num.end());
}
};
5 后记
参考博客:31 Next Permutation