[LeetCode] 1053. Previous Permutation With One Swap 交換一次的先前全排列



Given an array of positive integers arr (not necessarily distinct), return the lexicographically largest permutation that is smaller than arr, that can be made with exactly one swap (A swap exchanges the positions of two numbers arr[i] and arr[j]). If it cannot be done, then return the same array.

Example 1:

Input: arr = [3,2,1]
Output: [3,1,2]
Explanation: Swapping 2 and 1.

Example 2:

Input: arr = [1,1,5]
Output: [1,1,5]
Explanation: This is already the smallest permutation.

Example 3:

Input: arr = [1,9,4,6,7]
Output: [1,7,4,6,9]
Explanation: Swapping 9 and 7.

Example 4:

Input: arr = [3,1,1,3]
Output: [1,3,1,3]
Explanation: Swapping 1 and 3.

Constraints:

  • 1 <= arr.length <= 104
  • 1 <= arr[i] <= 104

這道題給了一個正整數的數組,說是讓任意交換兩個數字,使得變成字母順序最大的一種全排列,但是需要小於原先的排列,若無法得到這樣的全排列(說明當前已經是最小的全排列),則返回原數組。通過分析題目中給的例子不難理解題意,根據例子2來看,若給定的數組就是升序排列的,則無法得到更小的全排列,說明只有遇到降序的位置的時候,才有可能進行交換。但是假如有多個可以下降的地方呢,比如例子1,3到2下降,2到1下降,這里是需要交換2和1的,所以最好是從后往前檢驗,遇到前一個數字比當前數字大的情況時,前一個數字必定是交換方之一,而當前數字並不是。比如例子3,數字4的前面是9,正確結果是9和7交換,所以還要從4往后遍歷一下,找到一個僅次於9的數字交換才行,而且數字相同的話,取坐標較小的那個,比如例子4就是這種情況。其實這道題的四個例子給的真不錯,基本各種情況都 cover 到了,贊一個~ 分析到這里,代碼就不難寫了,首先從后往前遍歷,假如當前數字大於等於前一個數字,直接跳過,否則說明需要交換的。從當前位置再向后遍歷一遍,找到第一個僅次於拐點的數字交換即可,注意下面的代碼雖然嵌套了兩個 for 循環,其實是線性的時間復雜度,參見代碼如下:


class Solution {
public:
    vector<int> prevPermOpt1(vector<int>& arr) {
        int n = arr.size(), mx = 0, idx = -1;
        for (int i = n - 1; i > 0; --i) {
            if (arr[i] >= arr[i - 1]) continue;
            for (int j = i; j < n; ++j) {
                if (arr[j] < arr[i - 1] && mx < arr[j]) {
                    mx = arr[j];
                    idx = j;
                }
            }
            swap(arr[i - 1], arr[idx]);
            break;
        }
        return arr;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1053


參考資料:

https://leetcode.com/problems/previous-permutation-with-one-swap/

https://leetcode.com/problems/previous-permutation-with-one-swap/discuss/838836/Java-O(n)

https://leetcode.com/problems/previous-permutation-with-one-swap/discuss/299244/Similar-to-find-previous-permutation-written-in-Java


LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM