week_9_ Next Permutation

Description

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]

Solution

思考问题的方式很直接,正如数数时数位要向前进位,排列也存在“进位”的情况。

长度为size的排列,其“进位”定义为:

对任意i∈[size-n, size-1),满足nums[i] >= nums[i+1],则需要向nums[size-n-1]进位。

举例如下:

对于排列[2,5,4,1],其末三位,满足5 > 4 > 1,故需要向第一位进位。

其进位方式与数位进位稍有不同,需从第一位向后寻找第一个大于自己的数位,5 > 4 > 2,故选择4。

将4与2交换,得到组合[4,5,2,1],由于末三位已经达到饱和,故颠倒后即可得到最小组合,即[4,1,2,5]。

综上,对算法总结如下:

① 申明变量begin与end,并初始化begin = size - 2,end = size - 1,用于对达到饱和的末尾子排列起始位置进行记录。

② 对begin,以nums[begin] >= nums[begin+1]为条件由后向前遍历,并递减begin。

③ 若begin = -1,则整个排列已经是所能得到的最大排列组合,直接对整个排列进行颠倒。

④ 否则,由nums[begin+1]向后遍历,寻找第一个大于nums[begin]的数,并与nums[begin]进行置换,而后对nums数组的[begin+1, end]进行颠倒

⑤ 算法结束

代码如下:

class Solution {
public:
	void nextPermutation(vector<int>& nums) {
		int begin, end;
		int size = nums.size();
		if (size > 1) {
			begin = size - 2;
			end = size - 1;
			while (begin > -1 && nums[begin] >= nums[begin + 1])
				begin--;
			// 交换
			if (begin == -1)
				swapArray(nums, begin + 1, end);
			else {
				int pos = begin + 1;
				while (pos <= end && nums[pos] > nums[begin])
					pos++;
				int temp = nums[begin];
				nums[begin] = nums[pos - 1];
				nums[pos - 1] = temp;
				swapArray(nums, begin + 1, end);
			}
		}
	}
	// 颠倒顺序
	void swapArray(vector<int>& nums, int begin, int end) {
		for (int i = begin, j = end; i < j; i++, j--) {
			int temp = nums[i];
			nums[i] = nums[j];
			nums[j] = temp;
		}
	}
};

提交LeetCode的运行结果如下:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值