一、概述
傻逼题目。我看题目根本无法理解它的意思。什么叫“the lexicographically next greater permutation of numbers”。
直译过来是“按字典序的下一个更大的数字的排列”。十分模糊的概念。
后来试了无数次,见下图
才弄明白,这个下一个序列指的是:对于最后一个“先升后降的部分”,设峰顶前一个元素为a,在下降部分找到最小的大于a的元素b,swap一下a和b,然后重排b之后的元素。
我就想知道,我用这么长的句子总结出的概念,是如何表达成上面那个名词的。郁闷死。
后来发现可以这样表述:
输入一个序列,将其看做一个十进制整数,对于所有数字能够组成的所有数,找到最小的大于它的数。
lzzscl,还是难理解。
二、分析
1、我的算法
时空复杂度还可以,我就只讲我自己的了。这题目考的是语文,不是算法。见下图:
这是我一个一个修改输入才得到的输出序列,从上往下,上一个是下一个的输入,下一个是上一个的输出。
我们可以看到:
1234为升序,于是3与4调换;
1243先升后降,于是2与3调换;
1324升降升,于是2与4调换;
1342先升后降,于是3与4调换;
......
调换之后都有将后面的序列按从小到大重排序。
可以发现,a与b调换,a的位置是不变的,b的位置经常在变化。
a的位置是哪个呢?观察可知,a的位置可以按如下描述:
对于最后一个从na到nb的升序列,a的位置为nb-1。
b的位置也有讲究,对于最后的nc到nd的降序列,有时候b是最后一个,有时候是第一个。但是由于后面的序列元素不够,因此还需要更多的例子。
对于序列146532,其结果为152346,4与5调换。这次既不是第一个,又不是最后一个。
观察该序列可知。对于降序列6532,5是最小的大于4的元素。所以b的位置就这样确定了。
a和b的位置都确定之后,交换位置并重排序即可。代码如下:
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int len=nums.size();
if(len==1)
return;
int now=len-1;
int s=0;
int start=-1;
while(s<len-1)
{
if(nums[s]<nums[s+1])
start=s;
s++;
}
if(start==-1)
{
sort(nums.begin(),nums.end());
return;
}
int end=start+1;
for(int i=start+2;i<len;i++)
{
if(nums[i]>nums[start])
{
end=i;
}
else
{
break;
}
}
swap(nums[start],nums[end]);
sort(nums.begin()+start+1,nums.end());
return;
}
};
start用于找a,end用于找b。
别的没什么了。
三、总结
这题简直就是一个黑箱,题目解释屁用没有,我完全是靠自己调输入输出才得到的结果。