0

I stumbled upon a problem, maybe someone can give me pointers on how to solve it?

So, lets assume i have an array of objects (we can assume they're lists within a list), so something like that:

{ {1,2}, {2}, {1,2}, {3,4,5}, {1,2} }

The elements within the object appear only once (e.g. no duplicates like {2,2,4}). Before I thought I would need only two equal objects from the list of objects and double-looping worked the problem nicely, but now I need more and brute-forcing through array became really painful. So, how would I find indices of the {1,2} without creating ugly method with triple-quad-etc. looping?

Thank you

cpx
  • 17,009
  • 20
  • 87
  • 142
user1039063
  • 213
  • 3
  • 11
  • 2
    First ... is this homework? :) Second, if the array of objects is just an array of sorted integers (like you show) then it may be possible to optimize the problem. Another method may be to use some kind of hashing... – Ahmed Masud Nov 10 '11 at 05:59

3 Answers3

1

Easy way is to use a map where the key is the object and the value is an integer for the count. This way you can find it quicker. O(nlogn) or O(kn) for hashmap with no collisions.

Pseudo code (can't remember exact method signatures but you get the idea):

for (object o : myObjs)
{
    int num = 0;
    if (map.containsKey(o)) {
        map.put(o, map.get(o) + 1);
        num = map.get(o);
    } else {
        map.put(o, 1);
        num = 1;
    }
    if (num == 3)
        System.out.println("Object " + o + " has 3 members in set");
}
Jesus Ramos
  • 22,940
  • 10
  • 58
  • 88
0

You can sort the array using almost any comparator implementation you like, provided it reports logically equal objects to be equal. (Well, it also has to honor the transitive property of greater-than and less-than.) Then it's easy to use a linear scan through the sorted array to find runs of 3 or more.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
0

Building on Jesus Ramos' answer, the basic idea is to iterate over each sub-list, keeping track of how many times you see the contained element.

#include <vector>
using std::vector;
#include <map>
using std::map;

// input data
typedef vector< int > List;
typedef vector< int, List > ListOfLists;
ListOfLists input;

// temporary map for keeping track of how many times we see
// individual elements.  if you have boost or TR1, you can
// use unordered_map for a (possibly substantial) speedup.
typedef map< int, int > OccuranceMap;
OccurranceMap seen;

// now loop through all the sub-lists
for ( ListOfLists::const_iterator outer = input.begin(),
                                  oend  = input.end();
      outer != oend; ++outer )
{
    // and then iterate through all elements in each sublist
    for ( List::const_iterator inner = (*outer).begin(),
                               iend  = (*outer).end();
          inner != iend; ++inner )
    {
        // and keep track of how many we've seen.  using
        // operator[] is very slightly inefficient, but
        // shouldn't matter unless you have zillions of
        // distinct values.
        ++seen[*inner];
    }
}

// finally, go through the list of occurances and find those
// that showed up 3 times (or more than 3, depends on your
// application of course; just change the conditional).
for ( OccuranceMap::const_iterator ci   = seen.begin(),
                                   cend = seen.end();
      ci != cend; ++ci )
    if ( (*ci).second == 3 )
        cout << "saw '" << (*ci).first << "'"
             << " " << (*ci).second << " times" << endl;

Depending on how long the individual sub-lists are, this might even be a better choice than double-looping just to find duplicates. The tradeoff is the extra memory storage for the occurance counts.

AnthonyFoiani
  • 504
  • 5
  • 7