在没有嵌套循环的列表中查找重复项?并将它们放在单独的列表中

时间:2018-12-05 01:58:10

标签: java algorithm duplicates

我目前正在解决一个必须优化一些代码的问题。最慢的方法之一是在列表中查找重复元素的方法。

方案中的重复项的工作方式如下:假设您有一个元素列表,每个元素都有两个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的字符串。

如果有人知道更快的方法。

1 个答案:

答案 0 :(得分:0)

只需检查xy值中的任何重复。

class Person{
    int id;
}
class Donor extends Person {}
class Patient extends Person {}

class Match {
    Donor donor;
    Patient patient;
}

private void test() {
    List<Match> matches = new ArrayList<>();
    list.addAll(...); // ID of donor-patient : (1, 2), (1, 2), (1, 3)

    List<Match> duplicates = new ArrayList<>();
    Set<Integer> donors = new HashSet<>();
    Set<Integer> patients = new HashSet<>();
    Set<Integer> duplicateDonors = new HashSet<>();
    Set<Integer> duplicatePatients = new HashSet<>();

    for (Match match : matches) {
        if (!donors.add(match.donor.id)) {
            duplicateDonors.add(match.donor.id);
        }

        if (!patients.add(match.patient.id)) {
            duplicatePatients.add(match.patient.id);
        }
    }

    for (Match match : matches) {
        if (duplicateDonors.contains(match.donor.id) || duplicatePatients.contains(match.patient.id)) {
            duplicates.add(match);
        }
    }
}

这使用了大量的HashSet,因为HashSetadd()的{​​{1}}的时间复杂度(以大O表示)是contains()。从理论上讲,这种方法是O(1),但是您需要做一个基准测试,看看它是否真的更快。