leetcode31. 下一个全排列
leetcode31. next permutation
这道题可以先从极端情况入手考虑:
- 
第一个全排列: 1 2 3 4 5,完全升序的
- 
最后一个全排列: 5 4 3 2 1,完全降序的
有一个很显然的结论:为了最小化我们的操作对字典序的影响,我们要尽量修改靠后的元素的顺序。
所以,我们能确定,我们需要从后向前扫描,寻找需要交换的元素。
而我们也已经确定,如果一段序列是单调下降的,那么它的字典序就没有增大的余地,所以我们可以得到这样的做法:
从后向前扫描,跳过单调递增的部分(对应正序的单调下降),在第一个转折点处,记录当前的元素,然后找到后面最小的、比这个点大的元素,对他们进行交换,然后对整个序列靠后的部分进行逆序,可以通过图片很直观地理解:
由于交换后,最后的一堆元素是倒序的,字典序是新顺序当中最大的,我们reverse一遍,就能变成最小的了。
代码:
# include <iostream>
# include <array>
# include <algorithm>
# include <vector>
class Solution {
public:
    void nextPermutation(std::vector<int>& nums) {
		int i = nums.size() - 2;
		while(i >= 0 && nums[i] >= nums[i + 1])
			i--;
		if (i < 0) {
			std::reverse(nums.begin(), nums.end());
			return;
		}
		int j = nums.size() - 1;
		while(j >= 0 && nums[j] <= nums[i]) 
			j--;
		std::swap(nums[i], nums[j]);
		std::reverse(nums.begin() + i + 1, nums.end());
    }
};
int main() {
	Solution s;
	std::vector<int> nums{1,1,5};
	s.nextPermutation(nums);
	for(auto x: nums) {
		std::cout << x << " ";
	}
	std::cout << std::endl;
}


 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号