leetcode-31-下一个排列
本题目在凌应标老师的《算法设计与分析》第八次作业中出现,可供参考。
题目描述:
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。1,2,3 → 1,3,23,2,1 → 1,2,31,1,5 → 1,5,1
要完成的函数:
void nextPermutation(vector<int>& nums)
说明:
1、这道题给定一个vector,里面装着各种数字,比如123这样子,要求按照字典序输出当前排列的下一种排列,比如123的下一种字典序排列就是132。
如果当前已经不存在更大的下一种排序,比如321,已经到达最大了,那么输出123,这种最小的字典序排列。
除此之外,只允许原地修改,使用额外常数级空间。
2、这道题挺有意思的,如果要求输出所有的排列情况,并且按照字典序排列,存储在vector中返回,你会怎么做?
笔者觉得也许可以参考leetcode-17-电话号码的字母组合这种思路来做。
回到当前这道题,我们写几个排列来看下情况,如下:
1234的下一个排列是1243,从后面找起,如果倒数第二个比倒数第一个小,那么交换两个的数值,结束。
1243的下一个排列是1324,从后面找起,倒数第二个不会比倒数第一个小,所以只能继续往前走,倒数第三个比倒数第二个小,所以我们只需要交换从倒数第三个开始的vector元素。
1324的下一个排列是1342,规则一样,从后面找起,倒数第二个比倒数第一个小,交换两个的数值,结束。
1342的下一个排列是1423,从后面找起,倒数第二个不会比倒数第一个小,所以只能继续往前走,倒数第三个比倒数第二个小,所以我们只需要交换从倒数第三个开始的vector元素。
……
1432的下一个排列是2134,从后面找起,发现只有第一位小于第二位,所以我们要交换整个vector中的元素。
通过上述举例,我们可以发现,如果前面一个的数值小于后面一个,那么我们就要交换从前面一个到vector最后面的所有元素。而如果不满足这个条件,那么继续往前走。
如果走到第一位了,发现还是不满足,那么说明当前排列已经是字典序最大的排列了,我们只需要两两交换一下,便可以变成字典序最小的排列。
那我们要怎样交换从前面一个到vector最后面的所有元素?
举个例子,2431的下一个排列,是3124。
我们往前走到第一位,才找到前一个元素2小于后一个元素4的情况,此时,我们继续从后面找起,找到大于前一个元素的第一个元素3,因为431这种排列,决定了从后面找起的第一个大于前一个元素的元素3,是大于前一个元素2的最小元素。
交换他们的数值,这时候变成3421。
接着从4开始,头跟尾两两不断交换,也就是我们最终要的结果,3124。
附上代码,如下:
void nextPermutation(vector<int>& nums)
{
int s1=nums.size()-1,s2=s1-1,i;//s1表示最后一位,s2表示我们最开始从倒数第二位开始找起
while(s2>=0)//一直找,找到前一个元素小于后一个元素的这种情况
{
if(nums[s2]<nums[s2+1])
break;
s2--;
}
if(s2==-1)//如果全程没找着,s2已经是-1了,那么说明当前是字典序最大的排列
{
for(int i=0;i<=s1/2;i++)//头跟尾两两不断地交换
swap(nums[i],nums[s1-i]);
}
else//如果找着了,nums[s2]这时候要跟后面大于nums[s2]的最小元素交换数值
{
i=s1;
while(i>s2)//找到大于nums[s2]的最小元素
{
if(nums[i]>nums[s2])
break;
i--;
}
swap(nums[s2],nums[i]);//两两交换数值
for(i=s2+1;i<=(s1+s2+1)/2;i++)//从s2+1这个位置开始,头跟尾两两不断地交换
swap(nums[i],nums[s1+s2+1-i]);
}
}
这道题有意思就有意思在,你发现你要再往前找一位来交换的时候,比如2431,你必须找到2,2是第一个小于后面元素4的元素,这时候你会发现2后面的排列刚好是从大到小的排列,是一个降序排列。
因为是降序排列,所以省去我们很多功夫,比如找到大于2的最小元素,只需要从后面找起,第一个大于2的3就是了。
再比如交换完2和3这两个数值,我们得到了3421,接下来我们从4开始,后面的元素(包括4本身),还是一个降序排列,继续头跟尾两两交换就可以了。
笔者最开始还想得挺复杂,比如什么逐一比较,找到大于2的最小元素;什么4之后的元素通过冒泡排序来调整顺序。但都不需要。
上述代码实测8ms,beats 100.00% of cpp submissions。
leetcode-31-下一个排列的更多相关文章
- Java实现 LeetCode 31下一个排列
		
31. 下一个排列 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列). 必须原地修改,只允许 ...
 - LeetCode 31. 下一个排列 | Python
		
31. 下一个排列 题目 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列). 必须原地修改, ...
 - LeetCode 31. 下一个排列(Next Permutation)
		
题目描述 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列). 必须原地修改,只允许使用额外常 ...
 - leetcode 31下一个排列
		
/** 验证一般情况(元素数目大于等于3)有几个情况分析:两个特殊情况: 6 5 4 3 2 1 完全反序,这种序列没有下一个排序,因此重新排序1 2 3 4 5 6 1 2 3 4 5 6 完全升序 ...
 - LeetCode:下一个排列【31】
		
LeetCode:下一个排列[31] 题目描述 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排 ...
 - Leetcode题库——31.下一个排列
		
@author: ZZQ @software: PyCharm @file: nextPermutation.py @time: 2018/11/12 15:32 要求: 实现获取下一个排列的函数,算 ...
 - Leetcode题目31.下一个排列(中等)
		
题目描述: 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列). 必须原地修改,只允许使用额外 ...
 - 【LeetCode】下一个排列【找规律】
		
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列). 必须原地修改,只允许使用额外常数空间. ...
 - 代码题(45)— 下一个排列、第k个排列
		
1.31. 下一个排列 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列). 必须原地修改,只 ...
 - [LeetCode] 31. Next Permutation 下一个排列
		
Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...
 
随机推荐
- 网页截图API接口,一键自动生成网页截图
			
背景 最近在开发一个小程序,其中有一个帮助模块,内容为帮助文章列表,文章内容为网站后台编辑的富文本格式.鉴于小程序的特殊性,其对html格式的富文本支持并不友好. 刚开始有人开发了wxparse插件, ...
 - ROS Navigation中的map_server地图包功能和使用
			
博客参考 http://wiki.ros.org/map_server 和 https://www.ncnynl.com/archives/201708/1897.html 1. 安装map_serv ...
 - 解决root@localhost's password:localhost:permission denied,please try again
			
背景:在装完Hadoop及jdk之后,在执行start-all.sh的时候出现 root@localhost's password:localhost:permission denied,please ...
 - 【转】简说GNU, GCC and MinGW (Lu Hongling)
			
原地址:https://my.oschina.net/u/588967/blog/73478 GNU, GCC, MinGW是开源社区常常要遇到的概念. 网上一般的解释比较繁琐, 让人如坠云雾. 本文 ...
 - CodeForces 686A Free Ice Cream (水题模拟)
			
题意:给定初始数量的冰激凌,然后n个操作,如果是“+”,那么数量就会增加,如果是“-”,如果现有的数量大于等于要减的数量,那么就减掉,如果小于, 那么孩子就会离家.问你最后剩下多少冰激凌,和出走的孩子 ...
 - Linux设备驱动模型底层架构及组织方式
			
1.什么是设备驱动模型? 设备驱动模型,说实话这个概念真的不好解释,他是一个比较抽象的概念,我在网上也是没有找到关于设备驱动模型的一个定义,那么今天就我所学.所了解 到的,我对设备驱动模型的一个理解: ...
 - platform总线驱动代码分析
			
/************************************************************************/ Linux内核版本:2.6.35.7 运行平台:三 ...
 - (匹配 Hopcroft-Karp算法)Rain on your Parade -- Hdu --2389
			
链接: http://acm.hdu.edu.cn/showproblem.php?pid=2389 不能用匈牙利,会TEL的,用Hopcroft-Karp Hopcroft-Karp课件 以前是寻找 ...
 - JAVA反射机制o
			
Reflection是Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说"自审",并能直接操作程序的内部属性.例如,使用它能获得 Java 类中 ...
 - 团体程序设计天梯赛L2-023 图着色问题                                                                                            2017-04-17 09:28             269人阅读              评论(0)              收藏
			
L2-023. 图着色问题 时间限制 300 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 图着色问题是一个著名的NP完全问题.给定无向图 G ...