Leetcode C++《热题 Hot 100-30》31.下一个排列

Leetcode C++《热题 Hot 100-30》31.下一个排列

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

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

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

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

在真实的面试中遇到过这道题?

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/next-permutation
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  1. 思路
  • 复杂不是很可行思路
    • 现在看到这些题目,我就想先暴力求解对吧,没有充分理解逆序对的概念
    • 字典序的下一个更大的排列,那就是从左到右遍历,如果数字变小了,那就swap 143258,这个的下一个字典序应该是145238
    • 如果一直递减, 证明就是最大的,nums进行反转输出
    • 如果一直递增,从第二个元素开始找到后面略大于原来元素的值,如果相等继续找第三个元素
    • 所以如果从左到右,有递减存在,比如x位置开始递减 nums[x] > nums[x+1]
      • 那在x之后找到比x位置略大的数,放在x的位置,并将后面的数字从大到小排序
      • 如果没有找到比x位置略大的数,那就找【x,】x之后比nums[x-1]略大的数放在x-1的位置
  • 正确思路
    • 我们可以逆序对来求解这个题目(找到“最小的”逆序对),空间复杂度为1,时间复杂度为n
    • 对于一个排列,从后往前找到第一个开始减小的index
    • 1 5 8 4 7 6 5 3 1, 找到的是4
    • 从4的位置找最小的比4大的数,如果递增一直往后,如果递减判断是不是比4大,找到5
    • 然后将4和5进行交换,变成了 1 5 8 5 [7 6 4 3 1]
    • 我们可以看到最后是逆序的,然后要把5之后位置变成顺序的,做一个反转
    • 如果已经是最大的了,比如 7 6 5 4 3 2 1 ,那从后到前就找不到第一个逆序对,最后做一个反转即可
  1. 代码
class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int i;
        bool flag = false;
        for (i = nums.size()-1; i > 0; i--) {
            if (nums[i-1] < nums[i]){
                flag = true;
                break;
            }
        }
        if (!flag)
            return reverseNum(nums, 0, nums.size()-1);
        
        int swap_index = i; 
        for (int j = i; j < nums.size(); j++) {
            if (nums[j] > nums[i-1]) {
                if (nums[j] <= nums[swap_index])   //等号不能忘记,因为要尽可能和后面的值swap,得到一个较小的,比当前序列大的序列
                    swap_index = j;
                if (j < (nums.size()-1) && nums[j+1] < nums[i-1])
                    break;
            }
        }
        //cout << i-1 << endl;
        //cout << swap_index << endl;
        swap(nums[i-1], nums[swap_index]);
        reverseNum(nums, i,  nums.size()-1);
    }

    // [start,end]
    void reverseNum(vector<int>& nums, int start, int end) {
        for (int i = 0; i < (end-start)/2+1; i++)
            swap(nums[start+i], nums[end-i]);
    }
};
发布了205 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Alexia23/article/details/104183039
今日推荐