Find common items in k sorted lists (assuming they can have duplicate values) in constant space

I was wondering what the most efficient solution is to find the intersection of k sorted lists of integers (provided that they can have duplicates). I have already come up with several solutions. But I was wondering if there is a way to do this in a constant space and with the best time complexity?

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]
+4
source share
5 answers

onsite approach

. 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] + " ");
}

.

, .

, (current).

current ( ). " ".

( ) ( ) ..

(D). O(D*N*logK), K - . , , .

+1

, , .

Place pointers at the start of each of the N arrays

Then repeat the following
    Check if all N elements are the same
    If yes, then
        Advance all N pointers by one
    If no, then
        Advance only the pointer of the smallest value
    Repeat this until all elements have been exhausted
0

, , .

    int[][] input = new int[][]{{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 k = 4;

    Map<Integer, Integer> counter = new HashMap<>();
    for (int[] oneArray : input) {
        for (int oneNumber : oneArray) {
            counter.merge(oneNumber, 1, (a, b) -> a + b);
        }
    }

    for (Map.Entry<Integer, Integer> countEntry : counter.entrySet()) {
        if (countEntry.getValue() % k == 0) {
            int numberOfHits = countEntry.getValue() / k;
            for (int kCount = 0; kCount < numberOfHits; kCount++) {
                System.out.println(countEntry.getKey());
            }
        }
    }
0

, , :)

Convert this list into a hash map where the key is an element of the list, and the value - tuple: {count, intersection_count, k_count}.

Now go to the rest of the lists: if the item in question is the key in the map with the conversion of the list into a hash map, set intersection_countto min(count-in-current-list, intersection_count)and increase k_count.

0
source

Try saving each data list as a collection or a multiset rather than a list. Sets have a built-in efficient way of finding intersections of sets.

0
source

Source: https://habr.com/ru/post/1677513/


All Articles