leetcode-31 下一个排列

本文介绍如何通过寻找特定元素位置并进行交换及反转操作来实现数组的下一个字典序排列。适用于升序排列数组,特殊情况处理也包含在内。

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

Eng version:

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, do not allocate 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. Find the largest index k such that nums[k] < nums[k + 1]. If no such index exists, the permutation is sorted in descending order, just reverse it to ascending order and we are done. For example, the next permutation of [3, 2, 1] is [1, 2, 3].
2. Find the largest index l greater than k such that nums[k] < nums[l].
3. Swap the value of nums[k] with that of nums[l].
4. Reverse the sequence from nums[k + 1] up to and including the final element nums[nums.size() - 1].

含义如下:

1.找到所有满足nums[k]<nums[k+1]的情形中,使k最大的那个

2.再找到所有满足nums[l]>nums[k]中,使l最大的那个

3.交换nums[k],nums[l]

4.对nums[k]之后的元素(不包括nums[k])进行反转,即可得到结果

大致思路是把大数往前提,之后再将后面的元素字典序变最小


代码如下:

class Solution {
public:
	void nextPermutation(vector<int>&nums) {
		int len = nums.size();
		int k = -1, l = 0, i = 0;//注意三个变量的初始化值

		for (i = len - 2/*即倒数第二个元素(逆序遍历)*/;i >= 0;--i)
			if (nums[i + 1] > nums[i]) {
				k = i;
				break;//因为是逆序,故此时得到的k一定是最大的
			}

		if (k == -1) {
			reverse(nums.begin(), nums.end());//此时代表原数组为逆序排列,故直接反转
			return;
		}

		//接下来找i
		for (i = len - 1;i >= 0;--i) {
			if (nums[i] > nums[k]) {
				l = i;
				break;
			}
		}

		//二者交换
		swap(nums[k], nums[l]);

		//再反转k之后的元素(不包括nums[k])
		reverse(nums.begin() + k + 1, nums.end());

	}
};

注:从以上代码中我们可以看到,k和l的取得都是从数组最后一个元素向前推进(逆序),这样的话即可实现思路中的效果,而不是像正向遍历那样,容易发生越界;此外我们将k初始化为-1(不对应索引),作用是如果遍历了一遍之后其值仍没有变的话,代表原数组按逆序排列,故直接反转后结束。

此外反转时要注意是按照指针的方式,而不是索引(例如nums[0])


参考:https://blog.youkuaiyun.com/xuanwozhe/article/details/72848521



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值