我偶然发现了一个问题,也许有人能指点我如何解决它?
所以,假设我有一个对象数组(我们可以假设它们是列表中的列表),所以像这样:
{ {1,2}, {2}, {1,2}, {3,4,5}, {1,2} }
对象中的元素只出现一次(例如,没有像{2,2,4})
这样的重复。在我认为我只需要对象列表中的两个相等对象之前,双循环很好地解决了问题,但现在我需要通过数组的更多和强制变得非常痛苦。那么,如何在不创建带有三重四元组等循环的丑陋方法的情况下找到{1,2}
的索引?
谢谢
答案 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;
根据各个子列表的长度,这可能比双循环更好,只是为了查找重复项。权衡是出现计数的额外内存存储。