全排列
 
 

给定一个没有重复数字的序列,返回其所有可能的全排列。

示例:

输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]

参考博客:https://blog.csdn.net/summerxiachen/article/details/60579623

思路: 举例 1 2 3 4

1.回想自己大脑里面对1234的全排列的情况。首先固定1,然后对2 3 4进行分类,也就是固定第二个数字,2  。再往下,就是{1,2} 对3 4进行选择。固定3,排列为 1,2,3,4

固定4,排列为1,2,4,3。

因此我们可以回想到我们对全排列的思路是: 先固定第一个数,剩下的数字进行全排列。比如1,2,3,4固定1之后,就是对2,3,4进行全排列。固定2之后,就是对3,4全排列。

T=【T=【x1,x1,x2,x3,x4,x5,........xn−1,xn】x2,x3,x4,x5,........xn−1,xn】

我们获得了在第一个位置上的所有情况之后(注:是所有的情况),对每一种情况,抽去序列TT中的第一个位置,那么对于剩下的序列可以看成是一个全新的序列

T1=【x2,x3,x4,x5,........xn−1,xn】T1=【x2,x3,x4,x5,........xn−1,xn】

序列T1T1可以认为是与之前的序列毫无关联了。同样的,我们可以对这个T1T1进行与TT相同的操作,直到TT中只一个元素为止。这样我们就获得了所有的可能性。所以很显然,这是一个递归算法。

第一位的所有情况:无非是将x1x1与后面的所有数x2,x3,.......xnx2,x3,.......xn依次都交换一次

算法思路:全排列可以看做固定前i位,对第i+1位之后的再进行全排列,比如固定第一位,后面跟着n-1位的全排列。那么解决n-1位元素的全排列就能解决n位元素的全排列了,这样的设计很容易就能用递归实现。

代码如下:

class Solution {
List<List<Integer>> list=new ArrayList();      
public List<List<Integer>> permute(int[] nums) { if(nums.length==0)return list;
backTrace(0,nums.length,nums);
return list;
}
public void backTrace(int i,int len,int [] nums){
if(i==len-1){ //回溯的返回条件
List<Integer> res=new ArrayList();
for(int j=0;j<len;j++){ //回溯到了最后一个数字,我们便可以输出数组
res.add(nums[j]);
}
list.add(res);
return ;
}
for(int j=i;j<len;j++){
swap(nums,i,j); //交换元素,全排列的思想
backTrace(i+1,len,nums); //继续回溯,改变i的值,使其向下探索
swap(nums,i,j); //探索找到一个排列后,需要向上回溯,因此要恢复原序列的排列
} }
public void swap(int[] nums,int i,int j){
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
}

存在相同元素的情况

上面的程序乍一看没有任何问题了。可是,如果我们对序列进行一下修改 array = {1, 2, 2}.我们看看运行的结果会怎么样。

[1, 2, 2]
[1, 2, 2]
[2, 1, 2]
[2, 2, 1]
[2, 2, 1]
[2, 1, 2]

这里出现了好多的重复。重复的原因当然是因为我们列举了所有位置上的可能性,而没有太多地关注其真实的数值。 
现在,我们这样来思考一下,如果有一个序列T = {a1, a2, a3, …, ai, … , aj, … , an}。其中,a[i] = a[j]。那么是不是就可以说,在a[i]上,只要进行一次交换就可以了,a[j]可以直接忽略不计了。好了,基于这样一个思路,我们对程序进行一些改进。我们每一次交换递归之前对元素进行检查,如果这个元素在后面还存在数值相同的元素,那么我们就可以跳过进行下一次循环递归(当然你也可以反着来检查某个元素之前是不是相同的元素)。 
基于这个思路,不难写出改进的代码。如下:

class Solution {
List<List<Integer>> res=new ArrayList();
public List<List<Integer>> permute(int[] nums) {
dfs(nums,0);
return res;
}
public boolean isSame(int[] nums,int start,int end){
for(int i=start;i<end;i++){
if(nums[i]==nums[end])return false;
}
return true;
}
public void dfs(int[] nums,int len){
if(len==nums.length-1){
List<Integer> list=new ArrayList();
for(int i=0;i<nums.length;i++){
list.add(nums[i]);
}
res.add(list);
}
for(int i=len;i<nums.length;i++){
if(!isSame(nums,len,i))continue;
swap(nums,i,len);
dfs(nums,len+1);
swap(nums,len,i); }
}
public void swap(int[] nums,int i,int j){
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
}

leetcode-全排列详解(回溯算法)的更多相关文章

  1. BM算法  Boyer-Moore高质量实现代码详解与算法详解

    Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...

  2. SVD在推荐系统中的应用详解以及算法推导

    SVD在推荐系统中的应用详解以及算法推导     出处http://blog.csdn.net/zhongkejingwang/article/details/43083603 前面文章SVD原理及推 ...

  3. LeetCode刷题191203 --回溯算法

    虽然不是每天都刷,但还是不想改标题,(手动狗头 题目及解法来自于力扣(LeetCode),传送门. 算法(78): 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明: ...

  4. LeetCode专题——详解搜索算法中的搜索策略和剪枝

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode专题第20篇文章,今天讨论的是数字组合问题. 描述 给定一个int类型的候选集,和一个int类型的target,要求返 ...

  5. Java虚拟机详解04----GC算法和种类【重要】

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  6. Java虚拟机详解04----GC算法和种类

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  7. (原创)详解KMP算法

    KMP算法应该是每一本<数据结构>书都会讲的,算是知名度最高的算法之一了,但很可惜,我大二那年压根就没看懂过~~~ 之后也在很多地方也都经常看到讲解KMP算法的文章,看久了好像也知道是怎么 ...

  8. 详解KMP算法

    转载注明出处:http://www.cnblogs.com/yjiyjige/p/3263858.html 什么是KMP算法: KMP是三位大牛:D.E.Knuth.J.H.Morris和V.R.Pr ...

  9. 详解zkw算法解决最小费用流问题

    网络流的一些基本概念 很多同学建立过网络流模型做题目, 也学过了各种算法, 但是对于基本的概念反而说不清楚. 虽然不同的模型在具体叫法上可能不相同, 但是不同叫法对应的思想是一致的. 下面的讨论力求规 ...

  10. 详解KMP算法【转】

    本文转载自:http://www.cnblogs.com/yjiyjige/p/3263858.html KMP算法应该是每一本<数据结构>书都会讲的,算是知名度最高的算法之一了,但很可惜 ...

随机推荐

  1. PAT——1001 害死人不偿命的(3n+1)猜想 (15)

    对给定的任一不超过1000的正整数n,简单地数一下,需要多少步(砍几下)才能得到n=1? 输入格式:每个测试输入包含1个测试用例,即给出自然数n的值. 输出格式:输出从n计算到1需要的步数. 输入样例 ...

  2. Intermediate_JVM 20180306 : 运行时数据区域

    Java比起C++一个很大的进步就在于Java不用再手动控制指针的delete与free,统一交由JVM管理,但也正因为如此,一旦出现内存溢出异常,不了解JVM,那么排查问题将会变成一项艰难的工作. ...

  3. DML-删除

    方式一:使用delete一.删除单表的记录★语法:delete from 表名 [where 筛选条件][limit 条目数]二.级联删除[补充]语法:delete 别名1,别名2 from 表1 别 ...

  4. python类的使用(类定义,构造器,类属性,方法)

    注:这里只描述使用方法,具体类的概念长篇大论就不要为难我这个懒人了. 总之一句话编程语言只是一个工具,会用就行,好用就行.打破砂锅问到底,我觉得有必要研究一下C,汇编,电子链路等. class clt ...

  5. 【模板】RMQ(计算区间最值)

    ①一维RMQ (1) dp[i,j] 表示从第i个数起连续2j个数中的(最大值min.最小值max.最大公约数gcd……),通过更改下列代码中的红色函数即可实现. (2) b数组放置所需查询的数列. ...

  6. 学习笔记 - 中国剩余定理&扩展中国剩余定理

    中国剩余定理&扩展中国剩余定理 NOIP考完回机房填坑 ◌ 中国剩余定理 处理一类相较扩展中国剩余定理更特殊的问题: 在这里要求 对于任意i,j(i≠j),gcd(mi,mj)=1 (就是互素 ...

  7. 配置SpringBoot方便的切换jar和war

    配置SpringBoot方便的切换jar和war 网上关于如何切换,其实说的很明确,本文主要通过profile进行快速切换已实现在不同场合下,用不同的打包方式. jar到war修改步骤 pom文件修改 ...

  8. Jqgrid利用正则匹配表达式正确移除html标签

    在使用JqGrid表格插件过程中,遇到一个问题:后台取出来的字段是带有Html标签的,于是将内容填充到表格之后,带有的html标签会把表格撑开或者每一行的内容显示不统一,导致非常难看,就像下图所示: ...

  9. 支付宝PC端的支付(PHP)

    现在的一个项目支付宝PC支付还是用的以前网关:https://mapi.alipay.com/gateway.do  (是支付宝 2012年7月13日的3.3版本) 所以现在要做下支付宝PC支付的升级 ...

  10. 基于原生JS封装数组原型上的sort方法

    基于原生JS封装数组原型上的sort方法 最近学习了数组的原型上内置方法的封装,加强了用原生JS封装方法的能力,也进一步理解数组方法封装的过程,实现的功能.虽然没有深入底层,了解源码.以下解法都是基于 ...