leetcode31. 下一个全排列

leetcode31. next permutation

这道题可以先从极端情况入手考虑:

  1. 第一个全排列:

    1 2 3 4 5,完全升序的

  2. 最后一个全排列:

    5 4 3 2 1,完全降序的

有一个很显然的结论:为了最小化我们的操作对字典序的影响,我们要尽量修改靠后的元素的顺序。
所以,我们能确定,我们需要从后向前扫描,寻找需要交换的元素。

而我们也已经确定,如果一段序列是单调下降的,那么它的字典序就没有增大的余地,所以我们可以得到这样的做法:

从后向前扫描,跳过单调递增的部分(对应正序的单调下降),在第一个转折点处,记录当前的元素,然后找到后面最小的、比这个点大的元素,对他们进行交换,然后对整个序列靠后的部分进行逆序,可以通过图片很直观地理解:

pAqxldg.png

由于交换后,最后的一堆元素是倒序的,字典序是新顺序当中最大的,我们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;
}

本文作者:Gold_stein

本文链接:https://www.cnblogs.com/smartljy/p/18611098

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Gold_stein  阅读(5)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
🔑
  1. 1 逃离地面 RAD & 三浦透子
逃离地面 - RAD & 三浦透子
00:00 / 00:00
An audio error has occurred.

作词 : 野田洋次郎

作曲 : 野田洋次郎

空飛ぶ羽根と引き換えに 繋ぎ合う手を選んだ僕ら

それでも空に魅せられて 夢を重ねるのは罪か

夏は秋の背中を見て その顔を思い浮かべる

憧れなのか、恋なのか 叶わぬと知っていながら

重力が眠りにつく 1000年に一度の今日

太陽の死角に立ち 僕らこの星を出よう

彼が眼を覚ました時 連れ戻せない場所へ

「せーの」で大地を蹴って ここではない星へ

行こう

もう少しで運命の向こう もう少しで文明の向こう

もう少しで運命の向こう もう少しで

夢に僕らで帆を張って 来たるべき日のために夜を超え

いざ期待だけ満タンで あとはどうにかなるさと 肩を組んだ

怖くないわけない でも止まんない

ピンチの先回りしたって 僕らじゃしょうがない

僕らの恋が言う 声が言う

「行け」と言う