【LeetCode】Permutations 解题报告
全排列问题。经常使用的排列生成算法有序数法、字典序法、换位法(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的全排列例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGppYWJpbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
【代码实现】
因为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 解题报告
【LeetCode】Permutations 解题报告的更多相关文章
- LeetCode: Permutations 解题报告
Permutations Given a collection of numbers, return all possible permutations. For example,[1,2,3] ha ...
- 【LeetCode】46. Permutations 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 解题方法 方法一:库函数 方法二:递归 方法三:回溯法 日期 题目地址:h ...
- leetcode—Palindrome 解题报告
1.题目描述 Given a string s, partition s such that every substring of the partition is a palindrome. Ret ...
- LeetCode C++ 解题报告
自己做得LeetCode的题解,使用C++语言. 说明:大多数自己做得,部分参考别人的思路,仅供参考; GitHub地址:https://github.com/amazingyyc/The-Solut ...
- C++版 - 剑指offer之面试题37:两个链表的第一个公共结点[LeetCode 160] 解题报告
剑指offer之面试题37 两个链表的第一个公共结点 提交网址: http://www.nowcoder.com/practice/6ab1d9a29e88450685099d45c9e31e46?t ...
- LeetCode: Subsets 解题报告
Subsets Given a set of distinct integers, S, return all possible subsets. Note: Elements in a subset ...
- LeetCode: Triangle 解题报告
Triangle Given a triangle, find the minimum path sum from top to bottom. Each step you may move to a ...
- LeetCode: isSameTree1 解题报告
isSameTree1 Given two binary trees, write a function to check if they are equal or not. Two binary t ...
- LeetCode: Combinations 解题报告
Combinations Given two integers n and k, return all possible combinations of k numbers out of 1 ... ...
随机推荐
- 训练深度学习网络时候,出现Nan 或者 震荡
出现Nan : 说法1: 说法2:说法3: 震荡 : 分析原因: 1:训练的batch_size太小 1. 当数据量足够大的时候可以适当的减小batch_size,由于数据量太大,内存不够 ...
- [转]Spring mvc interceptor配置拦截器,没有登录跳到登录页
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.s ...
- php分享十五:php的数据库操作
一:术语解释: What is an Extension? API和扩展不能理解为一个东西,因为扩展不一定暴露一个api给用户 The PDO MySQL driver extension, for ...
- JDK1.7新特性,语言篇
1. 可以用二进制表达数字 可以用二进制表达数字(加前缀0b/0B),包括:byte, short, int, long // 可以用二进制表达数字(加前缀0b/0B),包括:byte, short, ...
- oracle11g exp导出问题:部分表导不出来
在oracle导出表的命令exp时候发现一个问题,就是部分表全然的导不出来,经检查发现仅仅要是表为空的都会导不出来. 在例如以下表中发现segment_created都为NO的是导不出来的,经查询后, ...
- 菜鸟学Java(三)——JSTL标签之核心标签
JSTL(JSP Standard Tag Library ,JSP标准标签库)是一个实现 Web应用程序中常见的通用功能的定制标记库集,这些功能包括迭代和条件判断.数据管理格式化.XML 操作以及数 ...
- SQL 中 replace 替换字符串中的字符 ''
update CfmRcd set reconsource=replace(reconsource,'''',''), cmffile =replace(cmffile,'''',''), cfmda ...
- linux命令(41):文件和文件夹的颜色
各个颜色的文件分别代表的是:蓝色表示目录:绿色表示可执行文件:红色表示压缩文件:浅蓝色表示链接文件:灰色表示其它文件:红色闪烁表示链接的文件有问题了:黄色是设备文件,包括block, char, fi ...
- Ubuntu 14.04环境变量修改
因在开发编译时是找不到命令,原因是将路径添加到环境变量,如何设置环境变量,搜索一下,找到以下关于环境变量设置的几个文件及何时执行. 首先要认识几个和环境变量有关的文件: /etc/profile —— ...
- muduo源码分析:组成结构
muduo整体由许多类组成: 这些类之间有一些依赖关系,如下: