我在处理数组中的重复元素时遇到了麻烦。例如,在查找数组中总和为指定值的所有整数对的问题中,这是我的实现:
vector<pair<int, int>> find_all_pairs_with_sum(int data[], int length, int sum)
{
assert(data && length>1);
vector<pair<int, int>> res;
sort(data, data+length);
int first = 0;
int last = length - 1;
while (first < last)
{
int s = data[first] + data[last];
if (s == sum)
{
res.push_back(make_pair(data[first], data[last]));
++first;
--last;
}
else
{
if (s < sum)
++first;
else
--last;
}
}
return res;
}
当数组包含重复元素时,将发生此问题。例如,
时int data[] = {3, 4, 3, 4};
int sum = 7;
该程序只会提供两对(3,4) (3,4)
。但是,在这种情况下,正确的答案应该是四对(3,4) (3,4) (3,4) (3,4)
(4 = 2x2)。如何修改代码以正确处理此类情况(希望仍然在O(n logn)
)?在更新if (s==sum)
和first
时,似乎应该在last
范围内进行更改,但我无法做到正确。
请注意:通过使用hash table
记录每个元素的出现次数,我知道另一种可以正确处理此问题的方法。请在不使用hash table
的情况下建议如何解决此问题。
答案 0 :(得分:2)
您的数组按
排序 Index: 0 1 2 3
Element: 3 3 4 4
当你找到一个总和时,你增加first
并减少last
,所以每对只增加一次,而不是两次。此外,以任何速度向内进行将始终阻止您同时获得1-3和0-2(按索引)。您可以进行初步传递以查找重复项,并使用该信息正确添加对:
vector<pair<int, int>> find_all_pairs_with_sum(int data[], int length, int sum)
{
assert(data && length>1);
vector<pair<int, int>> res;
int i;
sort(data, data+length);
// there is more than one way to skin this cat...
vector<pair<int, int>> vettedData;
for(i = 0; i < length; i++) {
if(i == 0 || vettedData[vettedData.size() - 1].first != data[i])
vettedData.push_back(make_pair(data[i], 1));
else
vettedData[vettedData.size() - 1].second++;
}
int first = 0;
int last = vettedData.size() - 1;
while (first < last)
{
int s = vettedData[first].first + vettedData[last].first;
if (s == sum)
{
int iterations = vettedData[first].second * vettedData[last].second;
for(i = 0; i < iterations; i++)
res.push_back(make_pair(vettedData[first].first, vettedData[last].first));
++first;
--last;
}
else
{
if (s < sum)
++first;
else
--last;
}
}
return res;
}