Java:两个有序整数序列的交集

时间:2012-09-13 13:19:57

标签: java arrays integer

  

可能重复:
  Java Compare Two Lists

如果我有两个有序的数字序列(我在这里有很多灵活性,并且可以将我的数据放入列表,集合,数组等),那么提取匹配的最有效方法是什么?例如,如果我有:

[1, 2, 4, 6, 9][2, 3, 4],我想返回[2, 4]

显然有很多方法可以解决这个问题;我很好奇最有效的方式是什么。

5 个答案:

答案 0 :(得分:10)

两个指针(索引),每个列表一个。从每个列表的开头

开始

每当您找到匹配项时,请将其存储起来。

如果您没有匹配项,请检查哪个列表在当前索引中具有最低值,并增加该列表的索引。检查一下比赛。这样做直到你到达其中一个列表的末尾。

线性运行到列表总和的大小(更糟糕的情况)。没办法做得更好。

答案 1 :(得分:4)

所以你想要集合的交集? 您可以使用apache commons中的CollectionUtils.intersection。或者更好,来自Guava的Sets.intersection(通用)。

答案 2 :(得分:2)

这是intersection两个集合,我猜Set是最佳选择。

请参阅Collection.retainAll()

  

仅保留此集合中包含在指定集合中的元素(可选操作)。换句话说,从此集合中删除未包含在指定集合中的所有元素。

更有效的方法是

public static void main(String[] args) {
    int[] firstArray = { 1, 3, 5, 8, 10 };
    int[] secondArary = { 3, 8 };
    //Arrays.sort(firstArray); If arrays needs to be sorted
    //Arrays.sort(secondArary);
    System.out.println(Arrays
            .toString(intersection(firstArray, secondArary)));

}

private static Integer[] intersection(int firstArray[], int secondArary[]) {
    int i = 0;
    int j = 0;
    ArrayList<Integer> list = new ArrayList<Integer>();
    while (i < firstArray.length && j < secondArary.length) {
        if (firstArray[i] < secondArary[j])
            i++;// Increase I move to next element
        else if (secondArary[j] < firstArray[i])
            j++;// Increase J move to next element
        else {
            list.add(secondArary[j++]);
            i++;// If same increase I & J both
        }
    }
    return list.toArray(new Integer[0]);
}

答案 3 :(得分:2)

如果您将两个序列存储到Set中,则可以使用Set.retainAll()

  

仅保留此集合中包含在指定集合中的元素(可选操作)。换句话说,从此集合中删除未包含在指定集合中的所有元素。如果指定的集合也是一个集合,则此操作会有效地修改此集合,使其值为两个集合的交集。

例如:

Set<Integer> s1 = new TreeSet<Integer>();
s1.add(1);
s1.add(2);
s1.add(6);

Set<Integer> s2 = new TreeSet<Integer>();
s2.add(2);
s2.add(6);

s2.retainAll(s1);

for (Integer i: s2)
{
    System.out.println(i);
}

输出:

2
6

答案 4 :(得分:1)

我会将两个列表创建为java.util.Set,将一个集合复制到临时变量并在此临时集上调用retainAll(<otherSet>)。然后临时设置将保留两组的交集。