题目意思是找到给出数字序列的下一个更大排列,比如给定1,2,3
那么就是找到比123大的数中最小的数,即132,那么它的排列就是1,3,2
;
思路:如果全都是降序的,那么肯定不存在比它大的排列,所以
step1:一定是找到里面的一个升序对,然后把大数与小数交换位置,比如12843,交换2,8得到18243,但如果交换1,2,就会得到比18243更大的21843,所以要从右向左找到第一对升序对;
step2:18243并不是大于12843的最小的数,原因是这个8太大了,很明显13842大于12843但比18243小,所以我们要在2的右边找到大于2的最小的数,把它与2交换即可,这里因为28是第一对升序对,所以2的后面一定都是降序的,所以只需从右向左找到大于2的最小的数,再交换,这里得到13842;
step3:经过以上两步,我们找到了13842,但它仍不是最小的,因为13248比12843大但比13842小,所以这里确定了13,我们就要把3后面的所有数改为升序排列,这样一定是最小的,因为 3后面是降序的,所以我们只需把它们翻转下即可;
下一个排列算法详解:思路+推导+步骤,看不懂算我输!
void nextPermutation(vector<int> &nums)
{
int len = nums.size();
if (len < 2)
{
return;
}
int i = len - 2, j = len - 1, k = len - 1;
//step1:从后向前找到第一对升序对
while (i >= 0 && nums[i] >= nums[j])
{
i--;
j--;
}
if (i < 0) //如果整个数组都是降序,那么设j=0,后面逆置nums[j~end]
{
j = 0;
}
else //找到升序对
{
//step2:从后向前找到第一个大于nums[i]的最小的数(肯定能找到)
while (k > i && nums[i] >= nums[k])
{
k--;
}
//交换nums[i]和nums[j]
int temp = nums[i];
nums[i] = nums[k];
nums[k] = temp;
}
//step3:逆置nums[j~end]
while (j < len - 1)
{
int temp = nums[j];
nums[j] = nums[len - 1];
nums[len - 1] = temp;
j++;
len--;
}
}