题目描述实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
题意解答:上边的1,2,3可以看成数字123,相当于找用1,2,3组成的数字种第一个比123大的数字,这个数字显然是132,所以答案是{1,3,2}
对于3,2,1这种已经是最大的数字的情况,直接逆序输出。
算法思路:不太好描述,所以举个例子。如2,3,2,1,从后往前遍历。
从1开始遍历,与相邻的前一个数字相比,前一个数字更大
继续遍历2,与相邻的前一个数字相比,前一个数字更大
继续遍历3,与相邻的前一个数字相比,前一个数字更小,此时停止遍历
同时,现在可以知道这个数字是2,继续用2向后比较,找到后边比他大的数字中最小的数字,可以知道这个数字是3。
交换2和3,此时得到3,2,2,1。然后将后边221的逆序,最后得到最终答案3,1,2,2
算法实现:
void swap(int* a,int* b){
int temp=*a;
*a=*b;
*b=temp;
}//交换
void reverse(int a[],int left,int right){
while(left<right){
swap(&a[left],&a[right]);
left++;
right--;
}
}//逆置
void nextPermutation(int* nums, int numsSize){
if(numsSize<2) return;//元素个数小于2时,直接结束
int i=numsSize-1;
while(i>0&&nums[i-1]>=nums[i]) i--;//从后往前遍历,直到遍历到的元素与前一个相邻元素相比,该元素更小
//如果i<1表示该数组时完全从大到小排列的,只需将其逆置即可
if(i<1){
reverse(nums,0,numsSize-1);
return;
}
int temp=nums[i-1],j=i;
//找到后边比他大的数字中最小的数字
while(j<numsSize&&temp<nums[j]) j++;
swap(&nums[i-1],&nums[j-1]);
reverse(nums,i,numsSize-1);
}