搜索&大整数集的差异

时间:2012-07-23 21:06:14

标签: java algorithm

我有2个大整数数组。我必须得到这些数组的差异(即第二个数组中的元素,而不是第一个,反之亦然)。我正在实现线性搜索并将差异存储在数组中。我有什么方法可以更快地完成它(线性时间)?

6 个答案:

答案 0 :(得分:2)

如果将一个数组放入哈希集然后运行另一个数组,探测哈希集,则很容易获得O(n + m)时间。当然,如果您的数组已经排序,那么您可以直接使用O(n + m)。

答案 1 :(得分:0)

我可能会说,取决于你的过度需求。您可以将列表分解为小集,并使用线程处理每个集合,将结果合并回集中池。

虽然不是太困难,但您需要进行一些管理,以便将结果组织回正确的顺序(因为线程2可能在线程1之前完成),并监视进程以了解它何时完成。

您可以查看Executors Tutorial了解更多信息

答案 2 :(得分:0)

哈希很好,但是设置数据结构呢?

stromberg@aw50 ~ $ /usr/local/pypy-1.9/bin/pypy
Python 2.7.2 (341e1e3821ff, Jun 07 2012, 15:38:48)
[PyPy 1.9.0 with GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
And now for something completely different: ``<arigato> the AI state is indeed
close''
>>>> s1 = set(range(10))
>>>> s2 = set(range(5,15))
>>>> s1
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>>> s2
set([5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
>>>> s1 - s2
set([0, 1, 2, 3, 4])
>>>> s2 - s1
set([10, 11, 12, 13, 14])
>>>> s1 & s2
set([8, 9, 5, 6, 7])
>>>> s1 | s2
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
>>>>

我猜这是一种方便的方法,对于同时适合内存的列表也很快。

还有像盘上BTrees或布隆过滤器这样的东西。

使用BTrees,您不必将所有内容都放在内存中,并且会像合并排序的合并步骤那样进行差异处理。它们基本上是一个有序的数据库表。

对于布隆过滤器,如果您需要过滤掉需要考虑的事物数量,它们非常适合;它们是概率性的,并且可以给出答案,例如“这绝对不是在集合中”和“这几乎肯定在集合中”。 bloom过滤器的主要好处是它们需要非常少的内存(有时每个元素只有一位)。好的实现将允许您指定最大允许错误概率。 EG,检测* ix硬链接几乎是一个集合成员问题,布隆过滤器非常适合 - 它们为您提供了一个可能的硬链接的简短列表,之后可以快速100%准确,因为硬链接的数量倾向于即使实际文件的数量很大,也要小。

答案 3 :(得分:0)

你不需要任何花哨的东西。如果您的数组已排序,那么单个遍历每个数组就足以获得差异。只需在每个数组中保留一个索引,如果索引指向相等的元素,则递增两个索引,否则将下部元素添加到返回数组并增加其索引。

以下是Go中的代码:http://play.golang.org/p/VZgGWmu-aO

这个解决方案需要O(n + m)时间和O(n + m)空间,你真的不能做得更好。此外,它没有涉及散列表的解决方案的开销。

答案 4 :(得分:0)

这是实现目标的直接方式:

public static Set<Integer> foundInFirstButNotSecond(int[] first,
        int[] second) {
    Set<Integer> secondSet = new HashSet<Integer>(second.length);
    for (Integer i :
            second) {
        secondSet.add(i);
    }
    Set<Integer> resultSet = new HashSet<Integer>(first.length);
    for (Integer j :
            first) {
        if (!secondSet.contains(j)) {
            // Current integer from first not found in second
            resultSet.add(j);
        }
    }
    return resultSet;
}

请注意,它会返回一个Set而不是一个数组,但如果更适合您,您可以轻松修改此代码以生成数组。

例如,如果您调用此代码:

public static void main(String[] args) {
    int[] first = new int[]{1, 2, 3, 4, 5, 6};
    int[] second = new int[]{5, 6, 7, 8};
    System.out.println("In first but not second: " + ArrayCompare.
            foundInFirstButNotSecond(first, second));
}

你会得到一个包含内容[1,2,3,4]的集合。 (请注意,HashSet不保证任何特定的顺序,所以你也可以得到一个无序的变化。)

答案 5 :(得分:0)

假设两个数组已排序,您可以使用两个滑动指针来查找差异。时间复杂度为O(n + m),空间为O(max(n,m))。

    void set_difference(std::vector<int> & array1,std::vector<int> & array2,std::vector<int> & output ) 
{
    auto index1 =  0 ;
    auto index2 = 0 ;
    while (index1 != array1.size() & index2 != array2.size()) 
    {       //since the arrays are sorted, we can stop looking right when we find a number bigger
        while ((array1[index1] < array2[index2]) & index2 != array2.size() )  
            index2++ ;
        if (array1[index1] != array2[index2]) //array1[index1] is not array2
            output.push_back(array1[index1]);
        index1++ ;
    }
}