题目:

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

For example,
[1,1,2] have the following unique permutations:
[1,1,2][1,2,1], and [2,1,1].

链接: http://leetcode.com/problems/permutations-ii/

题解:

求全排列,但元素可能有重复。去重复就成为了关键。今天好好思考了一下dfs+回溯,比如1134,最外层就是求出第一个元素,比如 1, 2, 3, 里面的嵌套dfs再负责第二,三,四个元素。 去重复的方法是传递一个visited数组,把排序后相同的元素看成一个cluster,假如nums[i] == nums[i - 1],但i-1没有被访问过,说明整个cluster不被访问,跳过整个cluster。

Time complexity - O(n!), Space Complexity - O(n)。

public class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
if(nums == null || nums.length == 0)
return res;
Arrays.sort(nums);
ArrayList<Integer> list = new ArrayList<Integer>();
boolean[] visited = new boolean[nums.length];
dfs(res, list, nums, visited);
return res;
} private void dfs(List<List<Integer>> res, ArrayList<Integer> list, int[] nums, boolean[] visited) {
if(list.size() == nums.length) {
res.add(new ArrayList<Integer>(list));
return;
} for(int i = 0; i < nums.length; i++) {
if(visited[i] || (i > 0 && nums[i] == nums[i - 1] && !visited[i - 1])) //skip duplicates
continue;
if(!visited[i]) {
visited[i] = true;
list.add(nums[i]);
dfs(res, list, nums, visited);
list.remove(list.size() - 1);
visited[i] = false;
}
}
}
}

二刷:

Java:

DFS + Backtracking:

一刷写的一坨屎...这遍依然不清不楚。 主要还是用了Permutation的代码,不同的地方是,我们使用了一个数组 - boolean[] visited。这个数组用来在dfs过程中记录已经访问过的值来避免计算重复。同时我们在dfs和backtracking的时候也要回溯这个数组。 经过上述步骤,我们就可以避免在dfs的时候有重复了。比如输入数组为[1, 1, 1], 则这个最后的结果 {[1, 1, 1]}是在最外层被加入到res中去的。   我们也要注意在遍历数组的时候,假如 visited[i]或者(i > 0 && nums[i] == nums[i - 1] && visited[i - 1]),要continue。

Time Complexity - O(n!), Space Complexity - O(n)

public class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
if (nums == null || nums.length == 0) {
return res;
}
Arrays.sort(nums);
boolean[] visited = new boolean[nums.length];
permuteUnique(res, new ArrayList<Integer>(), visited, nums);
return res;
} private void permuteUnique(List<List<Integer>> res, List<Integer> onePerm, boolean[] visited, int[] nums) {
if (onePerm.size() == nums.length) {
res.add(new ArrayList<>(onePerm));
return;
}
for (int i = 0; i < nums.length; i++) {
if (visited[i] || (i > 0 && nums[i] == nums[i - 1] && visited[i - 1])) {
continue;
}
visited[i] = true;
onePerm.add(nums[i]);
permuteUnique(res, onePerm, visited, nums);
onePerm.remove(onePerm.size() - 1);
visited[i] = false;
}
}
}

Iterative: Using Next Permutation:

我们依然可以使用Permutation I里面使用了求next permutation的代码, 完全搬移,都不用改的。 时间和空间复杂度还需要好好计算一下。这里有点混。

Time Complexity - O(n!), Space Complexity - O(n)

public class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
if (nums == null || nums.length == 0) {
return res;
}
Arrays.sort(nums);
Integer[] numsInt = new Integer[nums.length];
for (int i = 0; i < nums.length; i++) {
numsInt[i] = nums[i];
}
res.add(new ArrayList<>(Arrays.asList(numsInt)));
while (hasNextPermutation(numsInt)) {
res.add(new ArrayList<>(Arrays.asList(numsInt)));
}
return res;
} private boolean hasNextPermutation(Integer[] nums) {
for (int i = nums.length - 2; i >= 0; i--) {
if (nums[i] < nums[i + 1]) {
for (int j = nums.length - 1; j >= i; j--) {
if (nums[j] > nums[i]) {
swap(nums, i, j);
reverse(nums, i + 1, nums.length - 1);
return true;
}
}
}
}
return false;
} private void swap(Integer[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
} private void reverse(Integer[] nums, int i, int j) {
while (i < j) {
swap(nums, i++, j--);
}
}
}

三刷:

使用了和上一题一样的代码,也是next permutation的方法。

Java:

public class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
if (nums == null || nums.length == 0) return res;
Arrays.sort(nums);
do {
List<Integer> permu = new ArrayList<>();
for (int num : nums) permu.add(num);
res.add(permu);
} while (hasNextPermutation(nums));
return res;
} private boolean hasNextPermutation(int[] nums) {
int len = nums.length;
for (int i = len - 2; i >= 0; i--) {
if (nums[i] < nums[i + 1]) {
for (int j = len - 1; j > i; j--) {
if (nums[j] > nums[i]) {
swap(nums, i, j);
reverse(nums, i + 1, len - 1);
return true;
}
}
}
}
return false;
} private void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
} private void reverse(int[] nums, int i, int j) {
while (i < j) swap(nums, i++, j--);
}
}

Reference:

http://www.cnblogs.com/springfor/p/3898447.html

https://leetcode.com/discuss/25279/a-simple-c-solution-in-only-20-lines

https://leetcode.com/discuss/10609/a-non-recursive-c-implementation-with-o-1-space-cost

https://leetcode.com/discuss/18482/share-my-recursive-solution

https://leetcode.com/discuss/77245/line-python-solution-with-line-handle-duplication-beat-others

https://leetcode.com/discuss/62272/ac-python-clean-solution-108-ms

https://leetcode.com/discuss/55350/short-and-clean-java-solution

47. Permutations II的更多相关文章

  1. [Leetcode][Python]47: Permutations II

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 47: Permutations IIhttps://oj.leetcode. ...

  2. leetcode46. Permutations 、47. Permutations II、 剑指offer字符串的排列

    字符串排列和PermutationsII差不多 Permutations第一种解法: 这种方法从0开始遍历,通过visited来存储是否被访问到,level代表每次已经存储了多少个数字 class S ...

  3. 【LeetCode】47. Permutations II

    Permutations II Given a collection of numbers that might contain duplicates, return all possible uni ...

  4. leetCode 47.Permutations II (排列组合II) 解题思路和方法

    Permutations II  Given a collection of numbers that might contain duplicates, return all possible un ...

  5. [LeetCode] 47. Permutations II 全排列之二

    Given a collection of numbers that might contain duplicates, return all possible unique permutations ...

  6. 47. Permutations II (Back-Track, Sort)

    Given a collection of numbers that might contain duplicates, return all possible unique permutations ...

  7. 47. Permutations II (JAVA)

    Given a collection of numbers that might contain duplicates, return all possible unique permutations ...

  8. [leetcode] 47. Permutations II

    Given a collection of numbers that might contain duplicates, return all possible unique permutations ...

  9. LeetCode 【47. Permutations II】

    Given a collection of numbers that might contain duplicates, return all possible unique permutations ...

随机推荐

  1. WPF与DevExpress之旅-序言

    随着.NET技术的发展,从之前的WINFORM转向到WPF是我们技术改革的必然趋势.WPF能给人带来震撼的视觉体验,也能更加规范我们的开发模式,与传统的WINFORM开发来说具有革命性的意义.DevE ...

  2. 2014年互联网IT待遇(包括国内民企、外企、金融机构)

    一.民企 1. 百度 13k*14.6,special 14~17k*14.6 开发类 13K*14.6 (2014) 测试类.前端类 12K*14.6 (2014) 2. 腾讯 11.5k*16,s ...

  3. 对现有Hive的大表进行动态分区

    分区是在处理大型事实表时常用的方法.分区的好处在于缩小查询扫描范围,从而提高速度.分区分为两种:静态分区static partition和动态分区dynamic partition.静态分区和动态分区 ...

  4. Entity Framework4.0 (六) EF4的 增加、删除、更改

    前面介绍了EF4的查询功能,主要是借助于LINQ的强大的查询功能和它简单的语法.让我们可以完全面向对象集体去进行查询,而不必去劳心处理那些关系型数据库表的操作.这样我们更容易把主要精力集中在业务逻辑上 ...

  5. 使用ASP.NET注册工具aspnet_regiis.exe注册IIS

    该工具的名称为aspnet_regiis.exe,在32位机上,该工具存在于C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727,在64位机中“Framework ...

  6. 机器学习(Machine Learning)&深度学习(Deep Learning)资料【转】

    转自:机器学习(Machine Learning)&深度学习(Deep Learning)资料 <Brief History of Machine Learning> 介绍:这是一 ...

  7. CSS3展现精彩的动画效果 css3的动画属性

    热火朝天的css3无疑吸引了很多前端开发者的眼球,然而在css3中的动画属性则是新功能中的主打招牌,说到css3的动画属性不得不让人想起这三个属性:Transform﹑Transition﹑Anima ...

  8. 2012 Asia JinHua Regional Contest

    Draw Something http://acm.hdu.edu.cn/showproblem.php?pid=4450 o(n)统计输入每个数的平方和. #include<cstdio> ...

  9. windows下几种I/O端口(了解)

    如果你想在Windows平台上构建服务器应用,那么I/O模型是你必须考虑的.Windows操作系统提供了选择(Select).异步选择(WSAAsyncSelect).事件选择(WSAEventSel ...

  10. Oracle 临时事务表 全局临时表_global temporary table

    所有的操作都在一个事务里,事务提交后,此表清空,特别适合做插入删除频率特别高的临时表操作,比如插入完数据就开始查询,查询完就删掉等,用完就扔! 临时表分事务级临时表和会话级临时表. 事务级临时表只对当 ...