【每日一题】31. Next Permutation

时间:2022-07-22
本文章向大家介绍【每日一题】31. Next Permutation,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目描述

Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).

The replacement must be in-place and use only constant extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.

1,2,3` → `1,3,2`
`3,2,1` → `1,2,3`
`1,1,5` → `1,5,1

实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。

如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。

必须原地修改,只允许使用额外常数空间。

以下是一些例子,输入位于左侧列,其相应输出位于右侧列。

题解

首先想到的是,按顺序生成当前数组所有可能的排列组合,然后根据当前排列组合在其中的位置,如果是最后一个,返回第一个;否则,返回所在位置的下一个排列。为了保证不同排列符合题目的顺序,在生成所有组合之前,先进行升序排序,然后再进行排列。–但是这种情况,时间复杂度太高,而且不满足题目要求的空间复杂度要求

所以想到,根据上述的排列过程找出规律,根据给出的排列情况,直接生成下一个排列。

比如,对于数组1,2,3,4,5,下一个排列应该是1,2,3,5,4,下一个应该是1,2,4,3,5.变动的情况先发生在末尾,在以1,2,3,4之后只有一个5,下一个排列,应该保持1,2,3不动,整体变成1,2,3,5,4;

  1. 从后往前,先找到第一个不是降序排序的数字的下标;
  2. 如果下标<0,说明这个排列应该是最后一个,返回全序列的升序排序结果;
  3. 如果不为0,在这个元素之后找到第一个比它大的数字的下标,两者交换,对后续子数组做升序排序即可。

代码:

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        # 1,2,4,3,0
        if (nums.empty()) return;
        int size = nums.size(), i = size - 2, j = size - 1;
        
        while (i>=0 && nums[i] >= nums[i+1]) i--;
        
        if (i >= 0){
            while (nums[j] <= nums[i]) j--;
            swap(nums[i], nums[j]);
        }
        reverse(nums.begin()+i+1, nums.end());
    }
};

感觉说的不够清晰~

Reference

https://www.cnblogs.com/grandyang/p/4428207.html