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


在LeetCode中解决2Sum、3Sum4Sum问题时,利用双指针算法可以有效地提高解题效率。下面是针对每个问题的解决方法和时间复杂度分析。 参考资源链接:[Python双指针算法解LeetCode2/3/4Sum问题](https://wenku.youkuaiyun.com/doc/3s1mcqk5a2?spm=1055.2569.3001.10343) 2Sum问题的解决方法: a. 暴力解法:使用嵌套循环遍历数组中的每对元素,时间复杂度为O(n^2)。 b. 排序优化:对数组进行排序后使用双指针,时间复杂度为O(n log n)。 c. 哈希表结构:构建一个哈希表以存储元素值和其索引,时间复杂度为O(n)。 3Sum问题的解决方法: 由于问题要求找出所有不重复的三元组,因此在排序后使用双指针是较为有效的方法。首先对数组进行排序,然后对于数组中的每个元素,使用左右两个指针在该元素后面的数组中寻找满足条件的三元组。时间复杂度为O(n^2)。 4Sum问题的解决方法: 4Sum问题可以看作是3Sum问题的扩展,需要嵌套使用双指针技术。首先对数组进行排序,然后对于数组中的每个元素,考虑该元素后面的数组中是否存在两个数的和等于目标值减去该元素值的负数。时间复杂度为O(n^3),由于使用了排序,因此最坏情况下的时间复杂度会更高。 综上所述,双指针算法在处理这类问题时能够显著减少计算量,尤其在数组已经排序的情况下。通过合理运用排序和双指针技巧,我们可以将求解时间从指数级别降低到多项式级别,这对于算法性能的提升至关重要。如果需要更深入地理解双指针算法及其在这些问题上的应用,推荐阅读《Python双指针算法解LeetCode2/3/4Sum问题》。这份资源详细介绍了不同解法的代码实现,并且通过多个示例,帮助读者更好地掌握双指针算法的精髓。 参考资源链接:[Python双指针算法解LeetCode2/3/4Sum问题](https://wenku.youkuaiyun.com/doc/3s1mcqk5a2?spm=1055.2569.3001.10343)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值