java – 在常量空间中查找k个排序列表中的公共元素(假设它们可以具有重复值)

我想知道什么是找到k个排序整数列表的最有效解决方案(假设它们可以有重复).我已经提出了一些解决方案.但我想知道是否有任何方法可以在恒定的空间和最佳的时间复杂度中做到这一点?

Ex:
for k=4
[[1,2,3,3,4],[2,3,3,5],[1,2,3,3,5,6,7],[1,2,3,3,6,7,8,9]]
should return [2,3,3]

最佳答案 就地方法

您可以使用两个排序数组的略微更改的就地合并算法来就地查找交叉点.我们将有N-1(N是数组的数量)迭代.在每次迭代中,我们将第一个数组与具有i 1索引的数组合并.结果将写入第一个数组.像这样的东西:

http://ideone.com/NQznBV

private static int intersect(int[] a, int alen, int[] b) {
    int resLen = 0, bIndex = 0;
    for (int aIndex = 0; aIndex < alen; ++aIndex) {
        while (bIndex < b.length && a[aIndex] > b[bIndex]) ++bIndex;
        if (bIndex == b.length) break;

        if (a[aIndex] == b[bIndex]) {
            a[resLen] = a[aIndex];
            ++resLen;
            ++bIndex;
        }
    }
    return resLen;
}

private static int intersectArrays(int[][] arrays) {
    int len = arrays[0].length;
    for (int i = 1; i < arrays.length; ++i) {
        len = intersect(arrays[0], len, arrays[i]);
    }
    return len;
}

public static void main (String[] args) throws java.lang.Exception
{
    int[][] arr = {{1,2,3,3,4},{2,3,3,5},{1,2,3,3,5,6,7},{1,2,3,3,6,7,8,9}};
    int len = intersectArrays(arr);
    for (int i = 0; i < len; ++i)
        System.out.print(arr[0][i] + " ");
}

因此,我们有恒定的额外空间和线性时间复杂度.

另一种方法

如果我们无法改变输入,我们可以使用另一种算法.

首先,让我们取第一个数组(当前)的第一个数字.

然后,对于每个数组,我们可以在数组中找到此当前数字的出现次数(这可以通过两次二进制搜索来完成).然后输出这个数字“最小发生”次数.

然后我们将在第一个数组中找到下一个数字(大于前一个)(也使用二进制搜索),依此类推.

该算法的时间复杂度将取决于第一阵列(D)中的不同值的数量.它将等于O(D * N * logK),其中K – 数组的最大长度.值得注意的是,在某些情况下,该算法可能比上面的就地算法快得多.

点赞