二维列表去重

问题描述

题目需要返回二维列表,而且不能有重复元素。首先的想法就是使用集合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);

如有错误还请大家指正,不甚感激。

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值