问题描述
题目需要返回二维列表,而且不能有重复元素。首先的想法就是使用集合set去重,但结果仍然有重复元素。例如[[1, 0, -1], [0, -1, 1]]。代码示意如下:
List<List<Integer>> ans = new ArrayList<>(); //存放结果
List<Integer> temp = new ArrayList<Integer>();
ans.add(temp); //把每一个符合要求的结果temp都放入结果,此时包含重复元素
Set<List<Integer>> set = new HashSet<>(ans); //转成set去重
return new ArrayList<>(set);
分析:
集合set将[1, 0, -1]和[0, -1, 1]识别为不同的元素,说明此时两者的hash值可能不同。因此,个人判断hash值还与元素的顺序有关(具体计算方法可以查看源码)。为了验证自己的判断,写了如下代码。
List<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);
List<Integer> list2 = new ArrayList<>();
list2.add(2);
list2.add(1);
System.out.println(list1); //[1, 2]
System.out.println(list2); //[2, 1]
System.out.println(list1.hashCode()); // 输出:994
System.out.println(list2.hashCode()); // 输出:1024
Set<List<Integer>> set = new HashSet<>();
set.add(list1);
set.add(list2);
System.out.println(set); //[[2, 1], [1, 2]]
从输出结果可以看到,[1, 2]和[2, 1]的hash确实不同。而将元素顺序调整一样之后,set可以达到正常去重的效果。
List<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);
List<Integer> list2 = new ArrayList<>();
list2.add(1);
list2.add(2);
System.out.println(list1); //[1, 2]
System.out.println(list2); //[1, 2]
System.out.println(list1.hashCode()); // 输出:994
System.out.println(list2.hashCode()); // 输出:994
Set<List<Integer>> set = new HashSet<>();
set.add(list1);
set.add(list2);
System.out.println(set); //[[1, 2]]
总结:
当需要对列表去重时,要注意先对列表的元素进行排序,元素大小相同且顺序相同的列表hash值才相同。排序后再将列表放入set,就可以达到去重的效果。
因此,我对初始代码改进如下,结果正确。
List<List<Integer>> ans = new ArrayList<>(); //存放结果
List<Integer> temp = new ArrayList<Integer>();
Collections.sort(temp); //对列表元素排序
ans.add(temp); //排序后再将列表放入结果
Set<List<Integer>> set = new HashSet<>(ans); //转成set去重
return new ArrayList<>(set);
如有错误还请大家指正,不甚感激。