在准备采访时,我决定使用迭代器逻辑编写经典的“查找数组中有两个元素总结到给定数字”的问题,以便它可以推广到除{{之外的其他容器。 1}}。
到目前为止,这是我的功能
vector
当然,这不起作用,但如果不使用条件// Search given container for two elements with given sum.
// If two such elements exist, return true and the iterators
// pointing to the elements.
bool hasElementSum( int sum, const vector<int>& v, vector<int>::iterator& el1, vector<int>::iterator& el2 )
{
bool ret = false;
el1 = v.begin();
el2 = v.end()-1;
while ( el1 != el2 ) {
if ( *el1 + *el2 == sum ) return true;
++el1;--el2;
}
return false;
}
,我无法找到方法。我看来建议不要使用omnly对迭代器进行等式检查,以便能够推广到支持迭代器的所有类型的容器。
谢谢!
答案 0 :(得分:5)
首先,你的算法是错误的,除非你提前确定你只需要查看一个项目在集合的前半部分中的总和,另一个是收藏的后半部分。
如果输入没有排序,那么@ sbi的回答就差不多了。
使用排序的随机访问输入,您可以从第一个元素开始,并进行二分搜索(或插值搜索等)以查看是否可以找到必须使用的值来生成期望的总和。然后你可以尝试第二个元素,但是当你进行二分搜索(或其他)时,使用前一个搜索的结果作为上限。由于您的第一个元素大于前一个元素,因此产生正确总和的匹配值必须小于或等于您上次找到的值。
答案 1 :(得分:3)
foreach element1 in array
foreach element2 in array + &element1
if( element1 + element2 == sum )
return true
return false
这是O(N ^ 2),因为你必须将每个元素添加到每个其他元素。
答案 2 :(得分:2)
通常不会通过排序数组询问这个问题吗? 如果不是,它必须以O(n ^ 2)复杂度工作,并且你必须检查所有可能的对。
答案 3 :(得分:0)
我建议使用以下方法但不分析顺序
使用向量的所有元素构造二元搜索树,然后为每个元素构建
foreach(element = vec.begin to vec.end)
{
if element == node.data, skip
if the element + node.data == sum, return true
if the element + node.data > sum, goto left child
if the element + node.data < sum, goto right child
}
不是一个完美的解决方案/算法,但这类似的东西。
答案 4 :(得分:0)
抱歉,我搞砸了这个。我打算写的是一种线性传递后的线性传递,这是给出这个问题的典型答案,正如ltsik在他对Jerry的评论中指出的那样,即
bool hasElementSum( int sum, const vector<int>& v, int* ind1, int* ind2 )
{
*ind1 = 0; *ind2 = v.size()-1;
std::sort( v.begin(), v.end() );
while ( *ind1 <= *ind2 ) {
int s = v[*ind1] + v[*ind2];
if ( s > sum ) (*ind1)++;
else if ( s < sum ) (*ind2)++;
else return true
}
return false;
}
我的问题是如何使用迭代器来编写它而不说while (iter1 <= iter2 )
以便通用,但我现在看到这没有意义,因为这个算法无论如何都需要随机访问迭代器。此外,返回索引是没有意义的,因为它们引用已排序的数组而不是原始数组。