LeetCode 31. 下一個排列 Next Permutation (C語言)
阿新 • • 發佈:2018-12-24
題目描述:
實現獲取下一個排列的函式,演算法需要將給定數字序列重新排列成字典序中下一個更大的排列。
如果不存在下一個更大的排列,則將數字重新排列成最小的排列(即升序排列)。
必須原地修改,只允許使用額外常數空間。
以下是一些例子,輸入位於左側列,其相應輸出位於右側列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
題目解答:
方法1:逆向遍歷
要找到比之前更大的排列,肯定是要找到其中的某一位i
,並在其後(i + 1 ~~ n
)尋找到一個比num[i]大的數字,並交換兩者數字。但題目要求尋找下一個更大排列,所以就需要逆向遍歷需找到一個打破逆向遞增的位置,即從後向前找到一個nums[i]
nums[i+1]
小的位置,並在i
之後找到一個剛好大於num[i]
的數字(即比num[i]
大的數中的最小值),將兩者交換,並將i
之後的數字重新排序,排成有小到大的順序。另外就是特殊情況的處理,不存在更大的排列,就是直接返回升序排列。執行時間還4ms,程式碼如下。
void nextPermutation(int* nums, int numsSize) {
int i = 0, t = 0, t_index = 0;
// 從後向前尋找尋找打破遞增的位置
for(i = numsSize - 1; i > 0; i--) {
if(nums[i] > nums[i - 1]) {
t_index = i - 1;
t = nums[i - 1];
break;
}
}
if(i == 0) {
// 沒有下一個排列
for(i = 0; i < numsSize / 2; i++) {
t = nums[i];
nums[i] = nums[numsSize - 1 - i];
nums[numsSize - 1 - i] = t;
}
}
else {
// 從後向前尋找第一個比nums[t_index]大的位置,並交換。
for(i = numsSize - 1; i > t_index; i--) {
if(nums[i] > t) {
nums[t_index] = nums[i];
nums[i] = t;
break;
}
}
// 將後邊的餓重新排序,因為後邊的是一個從大到小的順序,所以交換法就可以。
for(i = 0; i < (numsSize - 1 - t_index) / 2; i++) {
int j = i + 1 + t_index;
t = nums[j];
nums[j] = nums[numsSize - i - 1];
nums[numsSize - 1 - i] = t;
}
}
return nums;
}