全排列问题。经常使用的排列生成算法有序数法、字典序法、换位法(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 解题报告的更多相关文章

  1. LeetCode: Permutations 解题报告

    Permutations Given a collection of numbers, return all possible permutations. For example,[1,2,3] ha ...

  2. 【LeetCode】46. Permutations 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 解题方法 方法一:库函数 方法二:递归 方法三:回溯法 日期 题目地址:h ...

  3. leetcode—Palindrome 解题报告

    1.题目描述 Given a string s, partition s such that every substring of the partition is a palindrome. Ret ...

  4. LeetCode C++ 解题报告

    自己做得LeetCode的题解,使用C++语言. 说明:大多数自己做得,部分参考别人的思路,仅供参考; GitHub地址:https://github.com/amazingyyc/The-Solut ...

  5. C++版 - 剑指offer之面试题37:两个链表的第一个公共结点[LeetCode 160] 解题报告

    剑指offer之面试题37 两个链表的第一个公共结点 提交网址: http://www.nowcoder.com/practice/6ab1d9a29e88450685099d45c9e31e46?t ...

  6. LeetCode: Subsets 解题报告

    Subsets Given a set of distinct integers, S, return all possible subsets. Note: Elements in a subset ...

  7. LeetCode: Triangle 解题报告

    Triangle Given a triangle, find the minimum path sum from top to bottom. Each step you may move to a ...

  8. LeetCode: isSameTree1 解题报告

    isSameTree1 Given two binary trees, write a function to check if they are equal or not. Two binary t ...

  9. LeetCode: Combinations 解题报告

    Combinations Given two integers n and k, return all possible combinations of k numbers out of 1 ... ...

随机推荐

  1. django 学习之model操作(想细化)

    一.Field选项 null=True 数据库为空 blank=True admin相关为空 choices:choices意味着静态数据的变化不会太大. db_column: 用于此字段的数据库的列 ...

  2. java将数据从List转换Map

    一.多对多 -> 一对多 二.代码实现 /** * 1个国家下所有城市,一对多关系 * 组装成Map结构返回 **/ public Map<String,List<JSONObjec ...

  3. PHP数组排序sort、asort与ksort用法

    分享下PHP数组排序之sort.asort与ksort用法,实例中简单示范了sort.asort与ksort的用法,并备有注释加以详细说明. PHP数组排序中sort.asort与ksort的用法. ...

  4. Python无限元素列表实例教程

    有关Python中无限元素列表的实现方法. 本文实例讲述了Python怎么实现无限元素列表的方法,具体实现可使用Yield来完成.下面所述的2段实例代码通过Python Yield 生成器实现了简单的 ...

  5. 通过反射实现圆角ImageView

    private void init(){ paint = new Paint(Paint.ANTI_ALIAS_FLAG); roundRect = , , getWidth() , getHeigh ...

  6. MinGW环境libssh2安装

    由于实习工作中要用到基于sftp协议开发一个网络程序,同时要实现运行在Windows平台上,找来找去就这个libssh2库好用,在网络上算是有那么一点点的文档可以看.这个库还不是现成的,还要进行源代码 ...

  7. 安卓数据解析之 fastjson 的解析以及Gson解析

    在安卓开发过程中的.我们经常使用的数据传递是以json格式传递.安卓 亲爹提供了我们Gson解析工具.点击下载Gson.jar 阿里巴巴FastJson是一个Json处理工具包,包含"序列化 ...

  8. # file Python-3.4.7.tar.xz Python-3.4.7.tar.xz: XZ compressed data

    # file Python-3.4.7.tar.xz Python-3.4.7.tar.xz: XZ compressed data # xz -d Python-3.4.7.tar.xz # ls ...

  9. [Windows Azure] How to Create and Deploy a Cloud Service?

    The Windows Azure Management Portal provides two ways for you to create and deploy a cloud service: ...

  10. Ctex中WinEdt经常弹出注册小窗口 解决办法

    使用WinEdt 7避免跳出“注册对话框” 在options菜单下点options…,在advanced configuration  =>  Event Handlers  下点Exit, 在 ...