1. 程式人生 > >LeetCode 31. 下一個排列 Next Permutation (C語言)

LeetCode 31. 下一個排列 Next Permutation (C語言)

題目描述:

實現獲取下一個排列的函式,演算法需要將給定數字序列重新排列成字典序中下一個更大的排列。
如果不存在下一個更大的排列,則將數字重新排列成最小的排列(即升序排列)。
必須原地修改,只允許使用額外常數空間。
以下是一些例子,輸入位於左側列,其相應輸出位於右側列。

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; }