【LeetCode】Permutations 解题报告
来源:互联网 发布:ubuntu chroot 编辑:程序博客网 时间:2024/05/22 04:58
全排列问题。常用的排列生成算法有序数法、字典序法、换位法(Johnson(Johnson-Trotter)、轮转法以及Shift cursor cursor* (Gao & Wang)法。
【题目】
Given a collection of numbers, return all possible permutations.
For example,[1,2,3]
have the following permutations:[1,2,3]
, [1,3,2]
, [2,1,3]
, [2,3,1]
, [3,1,2]
, and [3,2,1]
.
这是比较直观的思路。但是也有要注意的地方,刚开始写的时候,没有注意到list是共用的,所以前面得到的答案后面会改掉而导致错误。
public class Solution { List<List<Integer>> ret = new ArrayList<List<Integer>>(); public List<List<Integer>> permute(int[] num) { int len = num.length; if (len == 0) return ret; List<Integer> list = new ArrayList<Integer>(); run(list, num); return ret; } public void run(List<Integer> list, int[] num) { if (list.size() == num.length) { //注意这里要重新new一个list,要不然后面会被修改 List<Integer> res = new ArrayList<Integer>(); res.addAll(list); ret.add(res); return; } for (int i = 0; i < num.length; i++) { if (list.contains(num[i])) { continue; } list.add(num[i]); run(list, num); list.remove(list.indexOf(num[i])); //不要忘记这一步 } }}
【字典序法】
C++的STL库里面有nextPermutation()方法,其实现就是字典序法。
下图简单明了地介绍了字典序法
归纳一下为:
例如,1234的全排列如下:
【代码实现】
由于Java的list传参传的是地址,所以每次添加时都要记得重新new一个新的list添加到结果集中,否则添加到结果集中的原list会被后面的操作改变。
public class Solution { public List<List<Integer>> permute(int[] num) { List<List<Integer>> ret = new ArrayList<List<Integer>>(); int len = num.length; if (len == 0) return ret; Arrays.sort(num); //字典序法需先对数组升序排序 //数组转为list List<Integer> list0 = new ArrayList<Integer>(); for (int i = 0; i < len; i++) { list0.add(num[i]); } //把原始数组对应的list添加到结果中,不能直接添加list0,因为后面它会一直变化 List<Integer> ll = new ArrayList<Integer>(); ll.addAll(list0); ret.add(ll); //逐次找下一个排列 for (int i = 1; i < factorial(len); i++) { ret.add(nextPermutation(list0)); } return ret; } /***字典序法生成下一个排列***/ public List<Integer> nextPermutation(List<Integer> num) { //找到最后一个正序 int i = num.size()-1; while(i > 0 && num.get(i-1) >= num.get(i)){ i--; } //找到最后一个比num[i-1]大的数 int j = i; while(j < num.size() && num.get(j) > num.get(i-1)) { j++; } //交换num[i-1]和num[j-1] int tmp = num.get(i - 1); num.set(i - 1, num.get(j - 1)); num.set(j - 1, tmp); //反转i以后的数 reverse(num, i, num.size()-1); List<Integer> ret = new ArrayList<Integer>(); ret.addAll(num); return ret; } public void reverse(List<Integer> list, int begin, int end) { for(int i = begin, j = end; i < j; i++) { list.add(i, list.remove(j)); } } public int factorial(int n) { return (n == 1 || n == 0) ? 1 : factorial(n - 1) * n; }}
上面的实现需要先对原数组升序排序,下面对nextPermutation(List<Integer> num)改进后就不用对num排序了。
/***字典序法生成下一个排列***/ public List<Integer> nextPermutation(List<Integer> num) { //找到最后一个正序 int i = num.size()-1; while(i > 0 && num.get(i-1) >= num.get(i)){ i--; } //有了这个判断就不用num最初是按升序排好的了 if (i == 0) { reverse(num, 0, num.size()-1); List<Integer> ret = new ArrayList<Integer>(); ret.addAll(num); return ret; } //找到最后一个比num[i-1]大的数 int j = i; while(j < num.size() && num.get(j) > num.get(i-1)) { j++; } //交换num[i-1]和num[j-1] int tmp = num.get(i - 1); num.set(i - 1, num.get(j - 1)); num.set(j - 1, tmp); //反转i以后的数 reverse(num, i, num.size()-1); List<Integer> ret = new ArrayList<Integer>(); ret.addAll(num); return ret; }
欢迎高人对上述代码继续优化!
相关题目:【LeetCode】Next Permutation 解题报告 和 【LeetCode】Permutations II 解题报告
0 0
- [LeetCode]Permutations,解题报告
- 【LeetCode】Permutations 解题报告
- LeetCode-Permutations-解题报告
- [LeetCode] Permutations 解题报告
- Permutations [Leetcode 解题报告]
- 【LeetCode】Permutations II 解题报告
- [LeetCode] Permutations II 解题报告
- [leetcode] 46. Permutations 解题报告
- Permutations II [Leetcode 解题报告]
- LeetCode 46. Permutations 解题报告
- [Leetcode] 46. Permutations 解题报告
- [leetcode] 47. Permutations II 解题报告
- Leetcode # 46. Permutations 全排列 解题报告
- [Leetcode] 47. Permutations II 解题报告
- [leetcode]46. Permutations@Java解题报告
- [leetcode]47. Permutations II@Java解题报告
- Leetcode #47. Permutations II 全排列2 解题报告
- leetcode 之 Permutations 解题思路
- Akka边学边写(3)-- ByteString介绍
- 单源点的最短路径
- Python for Windows
- 书评第003篇:《0day安全:软件漏洞分析技术(第2版)》
- HDU 4770 Lights Against Dudely
- 【LeetCode】Permutations 解题报告
- OGEngine教程: 图片资源加载及工具使用
- Cocos2d-x Lua 使用Cocos Studio导出的动画
- ping 原理与ICMP协议
- c语言有头循环单链表
- 第8周项目3(1)-分段函数计算
- 2014十月——随笔。
- 程序设计中的函数(方法)的生命周期
- size balanced tree