0

I am supposed to write a code which is supposed to find the common elements existing in k collections of N-elements efficiently. All collections are sorted and they may have various sizes, but let's assume same sizes for the sake of simplicity here. Only thing that counts is the comparisons between elements; that should be less than O((k-1)*N).

I have developed the below code, but in case of mentioned scenario the number of comparisons is about (k-1)NN

Appreciate the help in advance.

//Arrays are sorted and the shortest array is chosen as the query automatically    
boolean com;
loop1: for (int i = 0; i < QuetyList.length; ++i) { 
    com = false;
    loop2: for (int k = 0; k < OtherLists.length; ++k) {
        com = false;
        loop3: for (int y = 0; y < OtherLists[k].size(); ++y) {
            ++comparisons;
            if (QueryList[i].compareTo(OtherLists[k][y]) == 0) {
                com = true;
                break loop3;
            }
            ++comparisons;
            if (QueryList[i].compareTo(OtherLists[k][y]) < 0) {
                break;
            }        
        }
        if (com == false) {
            break;
        }
    }
    if (com == true) {
        commons.add(QueryList[i]);
    }
}   

Sample test

Comparable [] QuetyList = {200,200,200,200};
Comparable [] collection2 = {2,10,50,200};
Comparable [] collection3 = {2,10,40,200};
Comparable [][] OtherLists = {collection2,collection3};

This is for a homework. There is a chance you may have crossed sometime in your education. Thanks in advance.

alexrnov
  • 2,346
  • 3
  • 18
  • 34
  • 1
    Are they hashable? Can you throw memory at it? Can you run through all the elements in each list, storing in a HashMap where value is a bitfield specifying which lists contain the key? If so, you don't really need the elements sorted. Otherwise, simplify the problem. First solve for k=2. Then try to extend. – MFisherKDX Feb 20 '18 at 04:49

1 Answers1

0

The basic idea is to keep an index on every list you have, and only advance this index when the value at the index is the smallest among all the lists.

I can't see if it's doable for k lists at once, but it's certainly doable 2 lists at a time, each should take N comparisons, which should give you O(k * N) (k-1 runs of N comparison).

Something like:

public Comparable[] common(Comparable[] a, Comparable[] b) {
    // List is more flexible, but the toArray at the end is a bit costly. You can probably figure a better way of doing this.
    List<Comparable> res = new ArrayList<>();
    int indexA = 0;
    int indexB = 0;
    while (indexA < a.length && indexB < b.length) {
        // Exercice for the reader: replace with compareTo calls
        if (a[indexA] == b[indexB]) {
            // Common item!
            res.add(a[indexA]);
            indexA++;
            indexB++;
        } else if (a[indexA] < b[indexB]) {
            // item in A is smaller, try the next
            indexA++;
        } else {
            indexB++;
        }
    }
    return res.toArray(new Comparable[0]);
}

From this, you can group your lists 2 by 2 until only one list remains.

njzk2
  • 38,969
  • 7
  • 69
  • 107