算法题丨Next Permutation
描述
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
算法分析
难度:中
分析:这里需要跟大家介绍一下相关的几个概念:
排列(Arrangement),简单讲是从N个不同元素中取出M个,按照一定顺序排成一列,通常用A(M,N)表示。当M=N时,称为全排列(Permutation)。
例如对于一个集合A={1,2,3},首先获取全排列a1: 1,2,3;然后获取下一个排列a2: 1,3,2;
按此顺序,A的全排列如下,共6种:
a1: 1,2,3; a2: 1,3,2; a3: 2,1,3; a4: 2,3,1; a5: 3,1,2; a6: 3,2,1;
从数学角度讲,全排列的个数A(N,N)=(N)*(N-1)*...*2*1=N!,但从编程角度,如何获取所有排列?那么就必须按照某种顺序逐个获得下一个排列,通常按照升序顺序(字典序lexicographically)获得下一个排列。
对于给定的任意一种全排列,如果能求出下一个全排列的情况,那么求得所有全排列情况就容易了,也就是题目要求实现的下一个全排列算法(Next Permutation)。
思路:
设目前有一个集合的一种全排列情况A : 1,5,8,4,7,6,5,3,1,求取下一个排列的步骤如下:
/** Tips: next permuation based on the ascending order sort * sketch : * current: 1 5 8 4 7 6 5 3 1 * | | | * find i----+ j +----end * swap i and j : * 1 5 8 5 7 6 4 3 1 * | | | * j----+ i +----end * reverse j+1 to end : * 1 5 8 5 1 3 4 6 7 * | | * find j----+ +----end * */
具体方法为:
a)从后向前查找第一个相邻元素对(i,i+1),并且满足A[i] < A[i+1]。
易知,此时从j到end必然是降序。可以用反证法证明,请自行证明。
b)在[i+1,end)中寻找一个最小的j使其满足A[i]<A[j]。
由于[j,end)是降序的,所以必然存在一个j满足上面条件;并且可以从后向前查找第一个满足A[i]<A[j]关系的j,此时的j必是待找的j。
c)将i与j交换。
此时,i处变成比i大的最小元素,因为下一个全排列必须是与当前排列按照升序排序相邻的排列,故选择最小的元素替代i。
易知,交换后的[j,end)仍然满足降序排序。
d)逆置[j,end)
由于此时[j,end)是降序的,故将其逆置。最终获得下一全排序。
注意:如果在步骤a)找不到符合的相邻元素对,即此时i=begin,则说明当前[begin,end)为一个降序顺序,即无下一个全排列,于是将其逆置成升序。
代码示例(C#)
public void NextPermutation(int[] nums) { int i = nums.Length - 2; //末尾向前查找,找到第一个i,使得A[i] < A[i+1] while (i >= 0 && nums[i + 1] <= nums[i]) { i--; } if (i >= 0) { //从i下标向后找第一个j,使得A[i]<A[j] int j = nums.Length - 1; while (j >= 0 && nums[j] <= nums[i]) { j--; } //交换i,j Swap(nums, i, j); } //逆置j之后的元素 Reverse(nums, i + 1, nums.Length); } //逆置排序 private void Reverse(int[] nums, int start, int end) { int i = start, j = end - 1; while (i < j) { Swap(nums, i, j); i++; j--; } } //交换 private void Swap(int[] nums, int i, int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; }
复杂度
- 时间复杂度:O (n).
- 空间复杂度:O (1).
附录
![]()
文章作者:原子蛋
文章出处:https://www.cnblogs.com/lizzie-xhu/
个人网站:https://www.lancel0t.cn/
个人博客:https://blog.lancel0t.cn/
微信公众号:原子蛋Live+
扫一扫左侧的二维码(或者长按识别二维码),关注本人微信公共号,获取更多资源。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
ElasticSearch_异常_01_org.elasticsearch.transport.ReceiveTimeoutTranspor...
一、异常信息 项目启动时 2018-04-17 16:32:16.496 INFO 15992 --- [ main] o.s.d.e.c.TransportClientFactoryBean : adding transport node : localhost:9300 2018-04-17 16:32:21.627 INFO 15992 --- [ main] org.elasticsearch.client.transport : [Thomas Halloway] failed to get node info for {#transport#-1}{127.0.0.1}{127.0.0.1:9300}, disconnecting... org.elasticsearch.transport.ReceiveTimeoutTransportException: [][127.0.0.1:9300][cluster:monitor/nodes/liveness] request_id [0] timed out after [5002ms] at org.elasticsear...
- 下一篇
Android反编译
一.尝试对demo进行反编译 应用打包成APK之后,把后缀名改成zip然后进行解压得到以下目录 这个就是APK的目录META-INF里面的是签名文件,res里面是资源文件,classes.dex就是我们的java代码编译后的文件 1.查看JAVA代码 既然能拿到classes.dex文件之后,我们就能有办法看到java的代码,这边需要两个工具: (1)dex2jar 这个工具能将dex文件转换成jar文件http://sourceforge.net/projects/dex2jar/files/ 下载dex2jar的解压包后解压,然后将classes.dex文件拷贝到解压后的目录下,命令行输入d2j-dex2jar classes.dex,比如我这里 然后得到相应的jar文件 (2)jd-gui这个工具能查看jar文件 官网我下不了,我是在网盘下的。 下载完之后打开exe文件,然后找到路径打开之前转换好的jar文件 这里就能找到我们在AS中写的java代码,当然并不会完全相同,但至少能看得懂。 2.apktool 上面的方法只是为了方便浏览APK中java的代码,但反编译中最主要的工具...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS6,CentOS7官方镜像安装Oracle11G
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2全家桶,快速入门学习开发网站教程
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- MySQL8.0.19开启GTID主从同步CentOS8
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池