使用散列在 3sum 问题中获取重复项

Posted

技术标签:

【中文标题】使用散列在 3sum 问题中获取重复项【英文标题】:getting duplicates in 3sum problem using hashing 【发布时间】:2019-05-09 06:34:44 【问题描述】:

我在做三和题3SUM 我知道更好的解决方案是使用两个指针。 但是我尝试了散列,我能够解决问题,但我是 得到重复的三胞胎。 尽管我尝试删除重复项,但我仍然得到它们。

// C++ program to find a triplet using Hashing 
#include <iostream>
#include<unordered_set>
#include<vector>
#include<algorithm>
using namespace std;
class Solution 
public:
    vector<vector<int>> threeSum(vector<int>& nums) 
        vector<vector<int>> output;
        unordered_set<int> seen;
        sort(nums.begin(), nums.end());
        for (int i = 0; i < nums.size(); ++i) 
            //removing duplicates
            if (i != 0 && nums[i] == nums[i - 1]) continue;

            for (int j = i + 1; j < nums.size(); ++j) 
                if (seen.count(-nums[i] - nums[j])) 
                    output.push_back( nums[i], nums[j], -nums[i] - nums[j] );
                    // Skip duplicates
                    while (j + 1 < nums.size() && nums[j + 1] == nums[j]) ++j;
                
                seen.insert(nums[j]);
            
        
        return output;
    
;



/* Driver program to test above function */
int main()

    vector<int> A =  -1,0,1,2,-1,-4 ;
    int sum = 13;
    int arr_size = sizeof(A) / sizeof(A[0]);
    vector<vector<int>> v;

    Solution s;
    v=s.threeSum(A);
    //printing duplicates here
    for (auto p : v) 
        for (auto m : p) 
            cout << m<<" ";
        
        cout << endl;
    

    return 0;

【问题讨论】:

这首先不检查sum 想想seen 在第一次迭代外循环 (i) 之后的样子。 【参考方案1】:

您正在对所有 i 使用 unordered_set seen,这会导致重复的三胞胎。更改 seen 的范围可以解决问题。请在下面找到正确的代码。

vector<vector<int>> threeSum(vector<int>& nums) 
        vector<vector<int>> output;
        sort(nums.begin(), nums.end());
        for (int i = 0; i < nums.size(); ++i) 
            //removing duplicates
            if (i != 0 && nums[i] == nums[i - 1]) continue;
            unordered_set<int> seen; //changed the scope of seen
            for (int j = i + 1; j < nums.size(); ++j) 
                if (seen.count(-nums[i] - nums[j])) 
                    output.push_back( nums[i], nums[j], -nums[i] - nums[j] );
                    // Skip duplicates
                    while (j + 1 < nums.size() && nums[j + 1] == nums[j]) ++j;
                
                seen.insert(nums[j]);
            
        
        return output;
    

解决这个问题的优化方法是使用两个指针而不使用任何额外的空间。

vector<vector<int>> threeSum(vector<int>& nums) 
        sort(nums.begin(), nums.end());
        int n = nums.size();
        vector<vector<int>> ret;
        for(int i=0;i<n;i++)
        
            if(i > 0 && nums[i] == nums[i-1]) continue;
            int j = i+1;
            int k = n-1;
            while(j < k)
            
                if(nums[i] + nums[j] + nums[k] == 0)
                
                    ret.push_back(nums[i], nums[j], nums[k]);
                    while(j < k && nums[j] == nums[++j]);
                    while(j < k && nums[k] == nums[--k]);
                
                else if(nums[i] + nums[j] + nums[k] < 0)
                    j++;
                else
                    k--;
            
        
        return ret;
    

【讨论】:

以上是关于使用散列在 3sum 问题中获取重复项的主要内容,如果未能解决你的问题,请参考以下文章

md5 散列在 swift 中封装返回

NSString 散列在不同版本的 iOS(不是 OS X)中具有相同的值吗?

Redis(开发与运维):13---哈希/散列对象

JavaScript 散集合(HashArray)

Python - 重复数据删除问题:TypeError:不可散列的类型:'numpy.ndarray'

10密码扩展