• [leetcode] 1503: Previous Permutation With One Swap


    思路

    1. 找到一个交换数A

    如果input各个数位上的值是按数位递增的,可以判断不能交换出数值更小的permutation。

    -> 反过来也就是说,如果input从右到左数位上的值全部是递减的就没有answer

    -> 说明如果不满足这个条件就说明可以进行置换,从右到左找到第一个违反递减顺序的数A,需要用A与某一个数位交换

        可以证明:1) A右边的数组是降序的,内部交换不能得到更小的值;2) A左边的数值权重更大,用A左边的数去跟某个数位交换得到的smaller value一定会比用A交换更小。

        所以用A交换才能得到比input原数值更小的、数值最大的permutation。(又是更小又是最大什么鬼好难表达

    2. 找到另一个交换数B

    另一个交换数B一定是在A的右边、数值比A小的数。

    因为:1) 如果A与左边的某个数C交换,要得到比input原值更小的数那么C一定比A大,在左边数位上降低数值影响的权重一定比在靠右数位上的大。

             2) A是第一个违反从右到左降序规律的元素,A右边一定存在比A数值更小的数。

    又因为A右边是从右到左降序排列的,B应该是其中比A小的数中最靠右的。但还有一点要考虑,A右边并不是严格降序排列的,可能存在与B相邻且与B值相等的数D,这种情况下应选择这组相邻相等的数中最靠左的。因为B和D一定比A小,要交换A和其中一个数获得最大的小值数(什么鬼表达)应该要让A和其中最靠左的数交换,把大数值的A放在权重尽量高的位置上。

    可以进一步推定B是在A右边、数值比A小的数中最靠右、如果有与其相等的相邻数则选其中最靠左(什么鬼真的好难表达

    总结:从右到左找到首个违反降序规律的数A,找到A数值比A小的数中“最靠右、相等相邻数中最靠左”的数B,交换AB。如果找不到A说明没有可交换数位。

    不会用数学语言证明我真的越来越垃圾了

    code

    class Solution {
    public:
        vector<int> prevPermOpt1(vector<int>& A) {
            int N=A.size(), left;
            for (left=N-1;left>0;left--) {
                if (A[left-1]>A[left])
                    break;
            }
            if (left==0)
                return A;
            --left;
            int right=N-1;
            while (A[right]>=A[left])
                --right;
            while (A[right]==A[right-1])
                --right;
            swap(A[left],A[right]);
            return A;
        }
    };
  • 相关阅读:
    关于session
    信息查找界面
    Java8 新特性 (三)Java内置的函数式接口
    第二节:表的管理
    【LeetCode-数组】有序数组中的单一元素
    【LeetCode-字符串】一次编辑
    【LeetCode-贪心】跳跃游戏 II
    【LeetCode-数组】三个数的最大乘积
    学习进度条94
    学习进度条93
  • 原文地址:https://www.cnblogs.com/RDaneelOlivaw/p/10958704.html
Copyright © 2020-2023  润新知