zoukankan      html  css  js  c++  java
  • 31. 下一个排列

    对于给定的某个排列,我们想求出比它大的最小的排列。

    可以从后往前遍历这个排列,找到第一个可以让排列的字典序变大的位置。

    只有当序列单调下降时,它才不存在更大的排列,因此我们要找的位置就是第一-次出现(nums[i] < nums[i+1]) 的位置。

    那么此时将 (nums[i])变成比它大的最小数,然后将剩余部分从小到大排序,这样可以在保证新排列大于原来排列的情况下,使变大的幅度尽可能小。。

    由于 (nums[i]) 后面的部分已经从大到小排好序,因此只需将其翻转,就可以得到从小到大排序的结果了。

    具体地,我们这样描述该算法,对于长度为 n 的排列 a:

    1. 首先从后向前查找第一个顺序对 ((i,i+1)),满足 (nums[i] < nums[i+1])。此时 ([i+1,n)) 必然是下降序列。
    2. 如果找到了顺序对,那么在区间 ([i+1,n)) 中从后向前查找第一个元素 (j) 满足 (nums[i] < nums[j])
    3. 交换 (numsi])(nums[j]),此时可以证明区间 ([i+1,n)) 必为降序。我们可以直接反转区间 ([i+1,n)) 使其变为升序,而无需对该区间进行排序。

    注意点

    • 如果在步骤 1 找不到顺序对,说明当前序列已经是一个降序序列,即最大的序列,我们直接跳过步骤 2 执行步骤 3,即可得到最小的升序序列。
    • 该方法支持序列中存在重复元素。
    class Solution {
    public:
        void nextPermutation(vector<int>& nums) {
            int i = nums.size() - 2;
            while (i >= 0 && nums[i] >= nums[i + 1])
                i--;
            if (i >= 0) {
                int j = nums.size() - 1;
                while (j >=0 && nums[j] <= nums[i])
                    j--;
                swap(nums[i], nums[j]);
            }
            reverse(nums.begin() + i + 1, nums.end());
        }
    };
    
  • 相关阅读:
    Alpha 冲刺 (7/10)
    Alpha 冲刺 (6/10)
    Alpha 冲刺 (5/10)
    Alpha 冲刺 (4/10)
    福大软工 · BETA 版冲刺前准备(团队)
    福大软工 · 第十一次作业
    Alpha 冲刺 (10/10)
    Alpha 冲刺 (9/10)
    Alpha 冲刺 (8/10)
    Alpha 冲刺 (7/10)
  • 原文地址:https://www.cnblogs.com/fxh0707/p/15064780.html
Copyright © 2011-2022 走看看