在没有嵌套循环的列表中查找重复项?

时间:2018-11-01 20:02:24

标签: java algorithm

我目前正在从事一项工作,我必须优化一些代码。最慢的方法之一是在列表中查找重复元素的方法。

方案中的重复项的工作方式如下: 假设您有一个元素列表,每个元素都有两个ID(x和y)。每个x值只能与一个y值配对,否则会将其视为重复项,并且原始和重复项都必须添加到列表中。

例如,元素列表为(1,2)(1,2)(1,3) 在这种情况下,重复项列表将包含4个元素(1,2,(1,3)和(1,2)(1,3),因为它们都具有相同的x值,但具有不同的y值。 (1,2)(1,2)不会归类为重复项,因为x和y值相同。

当前代码使用嵌套的for循环,该循环检查两个元素的x值是否相等,但y值不同,但这很慢。

在实际情况中,要素是与患者匹配的肾脏供体。因此,每个捐赠者只能向单个患者捐赠。 X和Y是代表患者和供体ID的字符串。

如果有人知道更快的方法,将不胜感激:)

4 个答案:

答案 0 :(得分:0)

您可以对具有x值的对数组进行排序。 然后将该数组切成具有相同x值的较小对对数组。 然后,使用当前算法,仅在较小的块中本地查找重复项。尽管它仍然具有嵌套循环,但执行起来会更快,因为搜索仅限于小数组,并且当n是元素数时,两个嵌套循环的搜索复杂度为O(n * n)。

答案 1 :(得分:0)

我只是给你一个提示 将其视为图形问题,并在(u,v)与以后之间绘制一条边,如果找到一个指向v的n边重复

答案 2 :(得分:0)

您可以尝试以下方法:

Map<Integer, Map<Integer, Long>> mmap = linkTable.stream()
      .collect(groupingBy(DonorsToPatientPair::getDonorID,
            groupingBy(DonorsToPatientPair::getPatientID, counting())));

变量mmap现在包含一个键映射到该键到频率的值映射。如果要获取(d,p)的出现次数,可以这样获得:

long freq = mmap.get(d).get(p)

要处理地图,可以使用如下代码:

for (int donor : mmap.keySet()) {
  Map<Integer, Long> patientMap = mmap.get(donor);
  if (patientMap.size() < 2) {
    continue; // no duplicates
  }
  // *** your code here ***
}

对于您自己的代码,您有一个循环的供体和一个从患者到他们的频率的映射。其余工作应该很容易完成。

答案 3 :(得分:-1)

您可以使用一组整数列表:

Set<List<Integer>> uniqueIds = new HashSet(listOfIds)

该工作由哈希集构造函数完成。