leetcode-31 下一个排列

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.csdn.net/xuanwozhe/article/details/72848521



阅读更多

没有更多推荐了,返回首页