处理重复的数组元素

时间:2014-01-10 06:58:33

标签: arrays duplicate-data

我在处理数组中的重复元素时遇到了麻烦。例如,在查找数组中总和为指定值的所有整数对的问题中,这是我的实现:

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的情况下建议如何解决此问题。

1 个答案:

答案 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;
}