描述:

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].

思路:

就该题来说,它是Permutation的进化版本,即该排列可能具有相同的元素。就Permutation这道题来说,假如第一次做的话

也不太好做,就是每次交换begin和后面的元素,然后在该位置的基础上在递归地调用排列方法并使得begin=begin+1,直

至begin=nums.length-1为止,然后将元素存储起来,详细步骤见代码。而Permutation II涉及到涉及到重复元素,在Permutation

的基础上进行修改的话,需要将将重复元素的这一段给过滤掉,具体的实现是用到

if(i!=begin&&arr[i]==arr[i-1])//当相邻元素相同时,仅能消除部分重复运算{continue;}

但是,即便这样,并不能过滤到所有的多余条件,比如说当当前所在的字符和前面的相同时,下一次执行到这里时i是和begin

相同的,所以会多算i==begin这一种情况。那怎么办呢?还有一种补救的方法(不完美,而且在leetcode上面运行程序会超时)

就是用HashSet来存储符合条件的list。下面直接上代码:

public class StringPermutation
{public void strPermute(Set<String>set,char arr[],int begin){if(begin==arr.length-1){set.add(new String(arr));}for(int i=begin;i<arr.length;i++){if(i!=begin&&arr[i]==arr[i-1])//当相邻元素相同时,仅能消除部分重复运算{continue;}swap(arr,begin,i);strPermute(set, arr, begin+1);swap(arr,begin,i);}}public void swap(char arr[],int index1,int index2){char temp=arr[index1];arr[index1]=arr[index2];arr[index2]=temp;}public static void main(String[] args){// TODO Auto-generated method stubStringPermutation stringPermutation=new StringPermutation();String string="303223";Set<String>set=new HashSet<String>();stringPermutation.strPermute(set, string.toCharArray(), 0);List<String>list=new ArrayList<String>(set);Collections.sort(list);//After sort,it's convinent to find the difference between the elementsIterator<String>iterator=list.iterator();while(iterator.hasNext())System.out.println(iterator.next());}}

效果:

而不用HashSet来处理这些重复元素呢,是这样的,代码如下:

public class StringPermutationII
{public void strPermute(List<String> list, char arr[], int begin){if (begin == arr.length - 1){list.add(new String(arr));}for (int i = begin; i < arr.length; i++){if (i != begin && arr[i] == arr[i - 1]){continue;}swap(arr, begin, i);strPermute(list, arr, begin + 1);swap(arr, begin, i);}}public void swap(char arr[], int index1, int index2){char temp = arr[index1];arr[index1] = arr[index2];arr[index2] = temp;}public static void main(String[] args){// TODO Auto-generated method stubStringPermutationII stringPermutation = new StringPermutationII();String string = "303223";List<String> list = new ArrayList<String>();stringPermutation.strPermute(list, string.toCharArray(), 0);Collections.sort(list);Iterator<String> iterator = list.iterator();while (iterator.hasNext())System.out.println(iterator.next());}}

效果如下,显然不适用HashSet的话会多出许多重复的元素,证明了上面的假设。

但list是对象啊,对象添加的不是对象的引用么?不同的对象的句柄又怎么可能相同呢?这就怪了,为了解开这个谜团,我专门写了两段小程序,来测试下set.add(Object obj),到底添加的是什么?

public class HashSetTest
{public static void main(String[] args){// TODO Auto-generated method stub//Test String
//      Set<String>set=new HashSet<String>();
//      String string="hello";
//      int count=100;
//      for(int i=0;i<count;i++)
//          set.add(string);
//      for(String str:set)
//          System.out.println(str);Set<List<String>>set=new HashSet<List<String>>();String string="hello";int count=100;for(int i=0;i<count;i++){List<String>list=new ArrayList<String>();list.add(new String("hello"));set.add(list);}for(List<String> list:set)System.out.println(list);}}

输出分别为:

hello

[hello]

可见即使是对象也是可以用HashSet去重的,真的是这样么?再上一段代码:

class User{String userName;public User(String userName){this.userName=userName;}
//  public int hashCode()
//  {
//      return this.userName.hashCode();
//  }
//  public boolean equals(Object obj)
//  {
//      if((obj instanceof User)==false)
//          return false;
//      if(this==obj)
//          return true;
//      return ((User)obj).userName.equals(this.userName);
//  }
}
public class HashSetTestII
{public static void main(String[] args){// TODO Auto-generated method stubSet<User>set=new HashSet<User>();int count=10;for(int i=0;i<count;i++){set.add(new User(new String("Sting")));}for(User user:set)System.out.println(user.userName);}}

输出结果:

不是这样啊,同样是对象为啥HashSet就不能对User去重呢,把注释去掉会怎样呢?

去掉注释后效果就变成

这下真相大白了吧,HashSet能不能对对象元素去重得看你是如何比较这个对象的,如果你重写了基类的hashCode()和equals()方法,

你就可以设计对象相等的标准,比如本题中userName相同就代表两个对象是相同的,就不可以放在同一个HashSet中。那String和List是

如何做到相同值的元素可以不插入一个HashSet中呢?很显然就像我们做的,这两个类重写了基类的那两个方法,该两个类进行比较时

String比较的是String的字符串的值,而List比较的是list中的每一个元素的值是否相等,有一个不像等就代表对象不等。

但是插入的时候对元素的比较是非常消耗时间的,所以才导致leetcode出现TLE的错误,也就是这种方法来去重成本太大了,而是可以

用更好的方法来解决该问题。

其实,HashSet添加的确实是对象的句柄,但是比较对象是否相等的时候是不是就是比较Object obj1,Object obj2中obj1==obj2呢,其实

,这得看该对象的hashCode(Obj obj)和equals(Obj obj)方法是否被覆盖,没有被覆盖的话确实比较的是对象的句柄,被覆盖的话比较的规则

就是hashCode(Obj obj)和equals(Obj obj)方法里所写的内容了。

leetcode_Permutations II相关推荐

  1. 剑指offer:面试题32 - II. 从上到下打印二叉树 II

    题目:从上到下打印二叉树 II 从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行. 例如: 给定二叉树: [3,9,20,null,null,15,7], 3    / \ ...

  2. 剑指offer:面试题14- II. 剪绳子 II

    题目:剪绳子 II 给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m.n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m] .请问 k[0]* ...

  3. 递归/回溯:Combination Sum II数组之和

    问题如下: 已知一组数(其中有重复元素),求这组数可以组成的所有子集中,子 集中的各个元素和为整数target的子集,结果中无重复的子集. 例如: nums[] = [10, 1, 2, 7, 6, ...

  4. 递归/回溯:Subsets II求子集(有重复元素)

    上一篇描述了针对数组中没有重复元素进行子集的求取过程递归/回溯:subsets求子集 但是当出现如下数组时: 例如: nums[] = [2, 1, 2, 2] 结果为: [[], [1], [1,2 ...

  5. HDU 2080 夹角有多大II

    夹角有多大II Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  6. 了解ES6 The Dope Way Part II:Arrow功能和'this'关键字

    by Mariya Diminsky 通过玛丽亚·迪明斯基(Mariya Diminsky) 了解ES6 The Dope Way Part II:Arrow功能和'this'关键字 (Learn E ...

  7. Leetcode 213.大家劫舍II

    打家劫舍II 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金.这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的.同时,相邻的房屋装有相互连通的防盗系统,如果两 ...

  8. 用Quartus II Timequest Timing Analyzer进行时序分析 :实例讲解 (一)

    一,概述 用Altera的话来讲,timequest timing analyzer是一个功能强大的,ASIC-style的时序分析工具.采用工业标准--SDC(synopsys design con ...

  9. 数据结构与算法:04 C#面向对象设计 II

    04 C#面向对象设计 II 知识结构: 5.属性 例1:属性概念的引入(问题) public class Animal {public int Age;public double Weight;pu ...

最新文章

  1. 网页转变成app,隐藏浏览器地址栏
  2. Hadoop学习笔记—4.初识MapReduce
  3. idea怎么搜索文件——search everywhere
  4. Socket、Tcp、Udp 概念区分
  5. [Everyday Mathematics]20150113
  6. Alex Hanna博士:Google道德AI小组研究员
  7. c语言中buf内容怎么给指针,C语言 指针的使用
  8. 【转】 C++中的new VS C语言中的malloc
  9. 查看php项目tp版本,tp5.1如何查看版本号
  10. C语言中控制printf的打印颜色实例及vt100的控制符文档-转
  11. PHP中cookies跨目录无法调用解决办法
  12. Linux时间子系统
  13. 中央企业经营管理一体化总体框架
  14. 在不同融资阶段,公司该如何估值
  15. Android学习笔记---集成百度语音合成的坑与坑
  16. 硬盘又坏了?硬盘数据恢复的工具有这些
  17. 厦门大学计算机科学与工程学院,厦门大学计算机系
  18. 宏基笔记本电脑怎么进入bios设置功能按键图解
  19. LVS+Keepalived之DR模式配置
  20. python 朴素贝叶斯算法

热门文章

  1. LED Designing
  2. scrollIntoView 滚不动
  3. CMD 调用子程序从子程序返回
  4. layui下载图片到本地
  5. 「网络安全」安全设备篇(7)——抗DDOS产品
  6. 律师程海认为北京市办理暂住证行为违法
  7. java导出excel表格,文件名称汉字话
  8. C语言第一个程序——一个简单的Hello world!程序
  9. 对比俩个List之间的差异
  10. RK3128-android5.1-wifi兼容