一个简单的全排列算法
- 什么是全排列?就是从n个数字中选择n个数字按照一定的顺序排列起来。
- 本文要讨论的算法要完成的任务是:给定一个数组,输出其所有的全排列结果。要求可以概括为两点:
- 输出该数组所有的全排列结果
- 任意两个全排列是不同的,即任意两个全排列中n个数字排列的顺序不能相同
- 其实核心思想就是枚举数组中每个位置的数字,而难点就是如何有序地枚举数组每个位置的数字而做到既全面又不重复。
- 首先我们以这个数组为a={1,2,3}为例,要找到它所有的全排列,这里我们用a[0],a[1],a[2]来表示这个数组中的第一、第二、第三个位置的数值,当前的数组各个位置的值为a[0]=1,a[1]=2,a[2]=3。于是算法可以分为以下几步来完成:
- 对a[0]的位置用1,2,3分别来替换,得到3个子序列
- 由于a[0]位置能取的所有的值的情况已经枚举完毕了,所以我们再对这3个子序列中a[1]位置所有能取的值再进行枚举。
- 到这里时,所有的子序列a[0]和a[1]都已经确定了,所以a[2]就自然已经确定了,只需要输出即可。图示如下:
其中,用红色的框标识出来的便是子序列,这里采用的是递归的方法,所以每一层实际上代表着递归的深度。
package nextPer;import java.util.Arrays;public class NextPer {public static void main(String[] args) {int[] arr={1,2,3};nextPer(arr,0);}private static void nextPer(int[] arr,int start){//当start==arr.length-1时,说明子序列的长度为1,就不用再往下分子序列了if(start==arr.length-1){System.out.println(Arrays.toString(arr));}for(int i=start;i<arr.length;i++){//start代表的是每一个子序列的第一个位置,我们每一层递归的任务都只有一个://枚举该层子序列第一个位置可以取的值int temp=arr[start];arr[start]=arr[i];arr[i]=temp;//该层递归的子序列第一个位置已经确定了,所以又可以往下再分nextPer(arr,start+1);//把第该层子序列第一个位置的值换成另外一个值,所以要交换回来temp=arr[start];arr[start]=arr[i];arr[i]=temp;}}
}
- 要明白这个算法的思想,只需要明白每一层递归在做的事:就是在不断地划分子序列,直到不能再划分为止,就可以输出该数组的值----即当子序列长度为1时,该子序列就不能再往下划分了。
- 在这里要注意几点:
- 由于递归的特性,是层层往下走,只有走到某个分支的末尾(我们叫做递归的出口)时才停止,然后再回溯(就是回到上一层),并把上一层的各个分支走完,再逐步往回走,所以结合输出结果和图示我们就可以知道,程序实际上在按从左到右一个分支一个分支地来走的。
- 这里的例子目的只是为了说明其算法思想,所以比较简单,但是我们的目的是可以对任意长度的数组进行全排列,只要明白这个算法的思路,就可以实现。我们暂时不考虑数组里面元素重复的情况,这其实可以先去重再用这个方法来实现。
- 这个例子可以帮我们理解递归的思想,但是递归的空间开销较大,所以使用递归的时候要注意有出口而且深度不要太深。
一个简单的全排列算法相关推荐
- lru算法实现 redis_使用数组与双向链表实现一个简单的LRU算法
什么是LRU算法? redis大家都玩过吧,你们好奇redis内存数据存满之后会发生什么吗?抛出异常?禁止使用?还是删除数据?其实redis设计了一种内润淘汰机制. noeviction(默认策略): ...
- 用C语言或C++编写一个简单的银行家算法模拟程序
1.问题描述 银行家算法是操作系统中避免死锁的典型算法.用C语言或C++编写一个简单的银行家算法模拟程序,实现多个进程争用系统临界资源时的分配过程.要求程序实现: 1.当一进程请求一组资源时,先确定是 ...
- Linux GCC下strstr的实现以及一个简单的Kmp算法的接口
今天做了一道题,要用判断一个字符串是否是另一个字符串的子串,于是查了一下strstr的实现. 代码如下: 1 char *strstr(const char*s1,const char*s2) 2 { ...
- 推荐算法的介绍以及实现一个简单的推荐算法(python实现协同过滤)
推荐算法: 推荐算法是计算机专业中的一种算法,通过一些数学算法,推测出用户可能喜欢的东西,目前应用推荐算法比较好的地方主要是网络,其中淘宝做的比较好. 发展背景: 推荐算法的研究起源于20世纪 ...
- 用C语言实现一个简单的一元线性回归算法
今天我们用C语言实现一个简单的线性回归算法:在代码前面我们在回顾一下线性回归. 线性回归是回归问题中的一种,线性回归假设目标值与特征是线性相关的,即满足一个多元一次方程式.通过构建损失函数,来求解损失 ...
- 一个简单的Apriltag,数字,动物水果分类器
简 介: 对于全国大学生智能车竞赛竞赛室内视觉AI组用于识别Apriltag,数字,动物以及水果任务,本文提出了基于图片像素的HSV空间的统计值,建立了一个简单的大类分类器.利用这个分类器可以非常精确 ...
- 蚁群算法画图java_[转载]简单蚁群算法 + JAVA实现蚁群算法
一 引言 蚁群算法(ant colony optimization,ACO),又称蚂蚁算法,是一种用来在图中寻找优化路径的机率型技术.它由Marco Dorigo于1992年在他的博士论文中引入,其灵 ...
- 蚁群算法java实现_简单蚁群算法 + JAVA实现蚁群算法
一 引言 蚁群算法(ant colony optimization,ACO),又称蚂蚁算法,是一种用来在图中寻找优化路径的机率型技术.它由Marco Dorigo于1992年在他的博士论文中引入,其灵 ...
- 论文翻译:DeepFaceLab:一个简单,灵活的可扩展换脸框架
DeepFaceLab:一个简单,灵活的可扩展换脸框架 时间有限,翻译仓促,为个人学习所用,仅供参考. DeepFaceLab: A simple, flexible and extensible f ...
最新文章
- docker 启动sqlserver_Docker mssql-server-linux:如何在构建期间启动.sql文件(来自Dockerfile)...
- HLS协议及java切片相关
- 查询条件中含有加号_excel中最全的多条件查询方法都在这里了
- html5基础知识点常用标签
- javascript实现面向对象的继承
- Asp.Net Core 工作单元 UnitOfWork UOW
- 表单新增元素与属性(control、placehoulder、list、AutoComplete、pattern、SelectionDirection、indeterminate属性)
- 西北工业大学计算机毕业论文,西北工业大学硕士论文开题报告应注意的事项
- ES5常用的组合继承及原型链理解
- 大数据教程(2.2):Linux系统安装JDK1.7
- 不使用border-radius,实现一个可复用的高度和宽度都自适应的圆角矩形
- vs2015编译ffmpeg
- 【算法笔记+BZOJ3676】回文串(回文树/回文自动机模版题)
- 【持续更新】总结国内外图形学物理模拟相关学者和网站
- java ehcache使用_ehcache使用报错
- 数学基础知识总结 —— 2. 常用积分公式
- php账单明细功能怎么实现,php 处理微信账单
- 深度学习 图像分割开源代码(附链接,超级全)
- AGV运行数据显示系统----工业物流
- 透明与不透明物体共存