Description:

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],
[2,1,1]
] Thoughts:
这个问题和之前的permutations问题类似,区别在于这次给定的数字有重复的部分,但是我们输出的排列又不允许重复。排列的话,一个数字不允许重复使用,之前在permutions中我们用Nums.contains来规避这个问题,但是在现在这个问题中因为
nums中有重复的数字,所以这个方法不行了,解决的办法是我们开辟一个和nums等长的boolean数组addnums,addnums中值为true,表示nums中对应位置上的数字已经被包含在排列中,就要跳过这个数字。通过这个方法我们就解决了基本的排列问题。
还有一个问题需要解决的就是排列不允许重复,这个问题的解决方法就是跳过那些已经作为首数字出现过的数字。首先我们对于原始数组进行一次排序,然后在每次选择数字的时候判断,对于大于首字符的数字是否等于首字符,并且还没有使用过,
如果是的话就跳过。以下是我的java代码:
package middle;
import java.util.*;
public class PermutationTwo {
public List<List<Integer>> permuteUnique(int[] nums){
List<List<Integer>> result = new ArrayList<List<Integer>>(); Arrays.sort(nums);
ArrayList addnums = new ArrayList();
trackBack(nums, new ArrayList(), result, addnums);
return result;
} private void trackBack(int[] nums, ArrayList arrayList,
List<List<Integer>> result, ArrayList addnums) {
// TODO Auto-generated method stub
if(arrayList.size()==nums.length && result.contains(arrayList)==false){
result.add(new ArrayList(arrayList));
}
for(int i = 0; i<nums.length;i++){
// if(i > 0 && nums[i] == nums[i-1]) continue;
if(addnums.contains(i)) continue;
arrayList.add(nums[i]);
addnums.add(i);
trackBack(nums, arrayList, result, addnums);
arrayList.remove(arrayList.size() - 1);
addnums.remove(addnums.size() - 1);
}
} public List<List<Integer>> permuteUniqueTwo(int[] nums){
List<List<Integer>> result = new ArrayList<List<Integer>>(); Arrays.sort(nums);
trackBackTwo(nums, result, new ArrayList(), new boolean[nums.length]); return result;
} private void trackBackTwo(int[] nums, List<List<Integer>> result,
ArrayList arrayList, boolean[] use) {
// TODO Auto-generated method stub
if(arrayList.size() == nums.length){
result.add(new ArrayList(arrayList));
}else{
for(int i = 0; i< nums.length;i++){
if(use[i] || i > 0&&nums[i] == nums[i-1]&&use[i-1]==false) continue;
use[i] = true;
arrayList.add(nums[i]);
trackBackTwo(nums, result, arrayList, use);
arrayList.remove(arrayList.size() - 1);
use[i] = false;
}
}
} public static void main(String args[]){
PermutationTwo p = new PermutationTwo();
int[] nums = new int[]{1, -1, 1, 2, -1, 2, 2, -1};
List<List<Integer>> list = p.permuteUniqueTwo(nums);
System.out.println(list);
} }

还有第二种更加直观的解法,但是它的执行时间太慢了,leetcode上通过不了,但是为了更加便于理解我还是把它写出来。解决重复数字的问题,我是用一个ArrayList记录当前已经使用过的数字的位置,如果当前数字的位置在ArrayList中已经
出现过了,那就说明当前的数字已经用过了,就要跳过。然后我们根据得到的排列,判断当前的排列是否包含在result中,如果包含了,也就是说当前的排列已经出现过了,那么该排列就不能加入到result中。换句话说,只有新的排列才能够出现在result
中。以下是我的java代码:
package middle;
import java.util.*;
public class PermutationTwo {
public List<List<Integer>> permuteUnique(int[] nums){
List<List<Integer>> result = new ArrayList<List<Integer>>(); Arrays.sort(nums);
ArrayList addnums = new ArrayList();
trackBack(nums, new ArrayList(), result, addnums);
return result;
} private void trackBack(int[] nums, ArrayList arrayList,
List<List<Integer>> result, ArrayList addnums) {
// TODO Auto-generated method stub
if(arrayList.size()==nums.length && result.contains(arrayList)==false){
result.add(new ArrayList(arrayList));
}
for(int i = 0; i<nums.length;i++){
// if(i > 0 && nums[i] == nums[i-1]) continue;
if(addnums.contains(i)) continue;
arrayList.add(nums[i]);
addnums.add(i);
trackBack(nums, arrayList, result, addnums);
arrayList.remove(arrayList.size() - 1);
addnums.remove(addnums.size() - 1);
}
} public static void main(String args[]){
PermutationTwo p = new PermutationTwo();
int[] nums = new int[]{1, -1, 1, 2, -1, 2, 2, -1};
List<List<Integer>> list = p.permuteUnique(nums);
System.out.println(list);
} }

PermutationTwo的更多相关文章

随机推荐

  1. 【翻译】Ext JS 6早期访问版本发布

    早期访问版本是什么 如何参与 都包括什么 Sencha Ext JS 6 Sencha Pivot Grid Sencha Cmd 6 JetBrains IDE插件 反馈 原文:Announcing ...

  2. Android性能优化之TraceView和Lint使用详解

    Android lint工具是Android studio中集成的一个代码提示工具,它主要负责对你的代码进行优化提示,包括xml和java文件,很强大.编写完代码及时进行lint测试,会让我们的代码变 ...

  3. android 4G产品4G网络问题记录

    电信.联通.移动切换到LTE_4G都不能通话(提示无法连接到网络)能正常上网,电信EVDO_3G不能通话(提示无法连接到网络)能正常上网这个是正常的,LTE只是针对上网,EVDO也是数据. 目前移动4 ...

  4. java实现http的post和get

    前话说一句:conn.setDefaultRequestProperty(key, value);这个函数是设置属性的,其实可以没有!   自己写了一个简单的get,容易控制 public stati ...

  5. sublimeText3使用记录

    sublime确实是神器,最近学习了一下,做个记录 1.下载 http://www.sublimetext.com/3 选择对应的版本安装即可(我的是win10 64位机) 2.个人配置 2.1.默认 ...

  6. Leetcode_144_Binary Tree Preorder Traversal

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42876699 Given a binary tree, r ...

  7. 求剁手的分享,如何简单开发js图表

    前段时间做的一个项目里需要用到js图表,在网上找了下,大概找到了highcharts.fusioncharts这些国外产品. 因为都收费,虽然有盗版,我也不敢用,万一被找上们来就砸锅卖铁了要.自己写j ...

  8. 插件化开发—动态加载技术加载已安装和未安装的apk

    首先引入一个概念,动态加载技术是什么?为什么要引入动态加载?它有什么好处呢?首先要明白这几个问题,我们先从 应用程序入手,大家都知道在Android App中,一个应用程序dex文件的方法数最大不能超 ...

  9. javase--day_01

    一.关键字: /*                            关键字:  被java语言复与特定含义的单词.      特点: 组成关键字单词的字母全部小写.   注意: A:goto和c ...

  10. AngularJS进阶(六)AngularJS+BootStrap实现弹出对话框

    AngularJS+BootStrap实现弹出对话框 参考资料: http://angular-ui.github.io/bootstrap/#/modal https://www.zybuluo.c ...