leetcode31-下一個排列
實現獲取下一個排列的函數,算法需要將給定數字序列重新排列成字典序中下一個更大的排列。
如果不存在下一個更大的排列,則將數字重新排列成最小的排列(即升序排列)。
必須原地修改,只允許使用額外常數空間。
以下是一些例子,輸入位於左側列,其相應輸出位於右側列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
題解
索引i由後往前遍歷數組,直到遇到某個數nums[i-1]<nums[i],
如果不存在,則說明該排列爲最大排列(逆序),則將其順序排序,變爲最小排列;
如果存在,第i-1個數小於第i個數,則在i右邊找到最小的大於第i-1個數的位置,記爲j(要知道此時i右邊的數字是逆序排列的,所以可以順序找到位置j),交換i-1和j上的數字,此時i右邊的數字還是逆序的,將其重排序爲升序,即可得到下一個排列。
這裏需要注意,在重排序時,因爲i右邊的數字們是降序的,所以將其重排序爲升序時,只需要交換第一個和最後一個數字、第二個和倒數第二個數字,…,以此類推,節省排序時間。
代碼如下:
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int listLen=nums.size();
for(int i=listLen-1; i>0; i--){
if(i==1 && nums[i-1]>nums[i]){
resortList(nums, 0, listLen-1);
break;
}
else if(nums[i-1] < nums[i]){
int j=i-1;
for(int j=listLen-1;j>i-1;j--){
if(nums[j]>nums[i-1]){
int k=nums[i-1];
nums[i-1]=nums[j];
nums[j]=k;
// swap(nums[j],nums[i-1]);
break;
}
}
// sort(nums.begin()+i,nums.end());
resortList(nums,i,listLen-1);
break;
}
}
// return nums;
}
void resortList(vector<int>& nums, int start, int end){
int k;
while(start<end){
int k=nums[start];
nums[start]=nums[end];
nums[end]=k;
// swap(nums[start],nums[end]);
start++;
end--;
}
}
};