在数组中找到3个或更多相等的对象?

时间:2011-11-10 05:50:21

标签: java c++ algorithm object equality

我偶然发现了一个问题,也许有人能指点我如何解决它?

所以,假设我有一个对象数组(我们可以假设它们是列表中的列表),所以像这样:

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

对象中的元素只出现一次(例如,没有像{2,2,4})这样的重复。在我认为我只需要对象列表中的两个相等对象之前,双循环很好地解决了问题,但现在我需要通过数组的更多和强制变得非常痛苦。那么,如何在不创建带有三重四元组等循环的丑陋方法的情况下找到{1,2}的索引?

谢谢

3 个答案:

答案 0 :(得分:1)

简单的方法是使用键是对象的映射,值是计数的整数。这样你就可以更快地找到它。 O(nlogn)或O(kn)用于没有冲突的hashmap。

伪代码(不记得确切的方法签名,但你明白了):

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

答案 1 :(得分:0)

您可以使用几乎任何您喜欢的比较器实现对数组进行排序,只要它报告逻辑上相等的对象是相等的。 (好吧,它还必须尊重大于和小于的传递属性。)然后,通过排序数组的线性扫描很容易找到3个或更多的运行。

答案 2 :(得分:0)

基于耶稣拉莫斯的回答,基本思想是迭代每个子列表,跟踪你看到所包含元素的次数。

#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;

根据各个子列表的长度,这可能比双循环更好,只是为了查找重复项。权衡是出现计数的额外内存存储。