#leetcode刷题之路31-下一个排列
程序员文章站
2022-03-30 11:29:46
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。必须原地修改,只允许使用额外常数空间。 以下是一些例子,输入位于左侧列,其相应输出位于右侧列。1,2,3 → 1,3,23,2,1 → 1,2, ......
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
思路:1.尝试一次遍历就解决问题。从后向前遍历数组,如果后一个总是比前一个大,那么排列就是最大的,这时需要反转排列。
2.如果在遍历过程中发现了一个比之前一个小的数,位置为i(此时i后面的数以降序排列,是最大值),此时反过来向后遍历,找到后面部分中最后一个比这个数大的数,交换两数(此时位置i后面的数降序排列,不过比之前的小),这时,i后面的数依然以降序排列,是最大值,但是我们想要得到的是下一个更大的排列,因此我们需要把i后面的数反序。即:小+最大排列-->大+最小排列
#include <iostream> #include <vector> using namespace std; void reverse(int begin,int end,vector<int>& nums)//用于反转序列 { while(begin<end) { int temp=nums[begin]; nums[begin]=nums[end]; nums[end]=temp; begin++; end--; } } void nextpermutation(vector<int>& nums) { int i; int len=nums.size(); if(len==0||len==1) return; if(len==2) {reverse(0,1,nums); return;} for(i=len-2;i>=0;i--) { if(nums[i]>=nums[i+1]) continue; else break; } if(i==-1) reverse(0,len-1,nums); //i记录要交换的位置 else { for(int j=len-1;j>=i+1;j--) { if(nums[j]>nums[i]) { int t=nums[j]; nums[j]=nums[i]; nums[i]=t; reverse(i+1,len-1,nums); break; } } } } int main() { vector<int> a={1,3,2}; nextpermutation(a); std::cout <<a[0] <<a[1]<<a[2]<< std::endl; return 0; }
上一篇: [SDOI2015] 序列统计