4sum

基本的 穷举前面的数的组合+后两个数夹逼法的算法:O(n^3):

1)排序

2)主循环穷举前两个数的组合,保证数组至少剩下2个数(i=0,i<n-3, j=i+1, j<n-2),注意去重,为什么可以跳过去?因为i,j当前取值下的剩余数组是之前取值下剩余数组的子数组,如果i, j的值之前有过,那么当前i,j下的解已经包含了。

3)  数组剩余部分应用两头夹逼法。注意去重


vector<vector<int> > fourSum(vector<int> &num, int target) {
        vector<vector<int>> output;
        int n = num.size();
        if(n<4) return output;
        sort(num.begin(),num.end());
        for(int i=0;i<n-3;i++)
        {
            if(i!=0 && num[i]==num[i-1])
                continue;
            for(int j=i+1;j<n-2;j++)
            {
                if(j!=i+1 && num[j]==num[j-1])
                    continue;
                int begin = j+1, end = n-1;
                while(begin<end)
                {
                    int sum = num[i] + num[j] + num[begin] + num[end];
                    if(sum== target)
                    {
                        vector<int> v;
                        v.push_back(num[i]);v.push_back(num[j]);v.push_back(num[begin]);v.push_back(num[end]);
                        output.push_back(v);
                        begin++; end--;
                        while(begin<end && num[begin]==num[begin-1])
                            begin++;
                        while(begin<end && num[end]==num[end+1])
                            end--;
                    }
                    else if(sum< target)
                        begin++;
                    else 
                        end--;
                }
            }
        }
        return output;
    }


借助map 的 O(n*n)算法,不需要排序,总体思路和2Sum的Map解法类似。 第一个O(n*n) 循环先用map缓存前两个数a,b组合的和,第二个O(n*n)循环枚举后两个数c,d,判断sum-c-d是否在map中。保证下标c,d 在 a, b之后。

 vector<vector<int> > fourSum(vector<int> &num, int target) {
        vector<vector<int>> output;
        int n = num.size();
        if(n<4) return output;
        sort(num.begin(),num.end());
        unordered_map<int,vector<pair<int,int>>> map;
        for(int i=0;i<n-3;i++)
        {
            if(i!=0 && num[i]==num[i-1])
                continue;
            for(int j=i+1;j<n-2;j++)
            {
                if(j!=i+1 && num[j]==num[j-1])
                    continue;
                map[num[i]+num[j]].push_back(pair<int,int>(i,j));
            }
        }
        for(int i=2;i<n-1;i++)
        {
            for(int j=i+1;j<n;j++)
            {
                if(j!=i+1 && num[j]==num[j-1])
                    continue;
                int x = target-num[i]-num[j];
                if(map.find(x)==map.end())
                    continue;
                for(auto it= map[x].begin();it<map[x].end();it++)
                {
                    if((*it).second<i)
                    {
                        int a[]={num[(*it).first],num[(*it).second],num[i],num[j]};
                        output.push_back(vector<int>(a,a+4));
                    }
                }
            }
        }
        sort(output.begin(),output.end());
        output.erase(unique(output.begin(),output.end()),output.end());
        return output;
    }


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值