[每日算法] leetcode第31题 Next Permutation

本文深入解析了下一排列算法,一种用于重新排列数字序列以获得字典序下一个更大的序列的算法。文章详细阐述了算法的步骤,包括寻找第一个非递增元素、定位大于该元素的最接近数值以及进行必要的交换和排序。提供了C++代码实现,帮助读者理解并掌握这一高效算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题目描述

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

题目大意

该题目给定一串数字,要求求出该数字串的下一置换,直接在原参数vector上进行操作,无需返回值.题意还是很好理解的,只要知道了什么是置换,了解置换的规则还是很好AC的。

解题思路

这里,我通过几个例子来说明如何求出下一置换:
例子:【2,1,3,8,6,5,4】
第一步,我们从数组末尾开始向前找,找出第一个非递增的数(这里的递增是从后往前算的),即 nums[i] < nums[i+1],这个例子我们可以找出这个数为3,我们记为num1;
特殊情况:如果找不到这样一个数,说明该数组是完全按递减排序的,此时我们只需要对其做个reverse便得到下一置换了)
第二步,如果第一步找到了num1,我们再次从数组末尾开始向前找,找到第一个比num1大的数(此处是一定能够找到了,因为第一步一经确定num1是第一个非递增的数),这个例子我们可以找到这个数为4,我们记为num2;
第三步,交换num1和num2,并将num2和num1(包括num1但不包括num2)之间的数按照升序排序,便得到下一置换,此处交换num1和num2得到【2,1,4,8,6,5,3】,将num2和num1(包括num1但不包括num2)之间的数排序,得到【2,1,4,3,5,6,8】,这便是结果。

C++实现代码

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int len = nums.size(), k = 1;
        if (len <= 1) 
            return;
        if (len == 2) {
            swap(nums[0], nums[1]);
            return;
        }
        for (int i = len-1; i >= 1; i--) {
            // 第一步,从末尾找出第一个非递增的数nums[i]
            if (nums[i] > nums[i-1]) {
                for (int j = len-1; j >= i; j--) {
                    // 第二步,从末尾找出找出第一个比nums[i]大的数nums[j]
                    if (nums[j] > nums[i-1]) {
                        // 交换并排序
                        swap(nums[j], nums[i-1]);
                        sort(nums.begin() + i, nums.end());
                        return;
                    }
                }
            }
        }
        // 如果未找到第一个递增的数,则翻转得到下一置换
        reverse(nums.begin(), nums.end());
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值