LeetCode 18. 4Sum

问题链接

LeetCode 18. 4Sum

题目解析

给定n元素的数组,求出满足 \(a+b+c+d = target\) 的所有元组。

解题思路

已经成为一个系列了,这道题是 LeetCode 15. 3Sum 的升级版,思路与其也是一模一样,外层再加一层循环。

先将数组排好序,便于检测重复。最外层循环固定最小数字 \(a\),第二层循环固定第二小数字 \(b\),左右指针分别代表 \(c\)\(d\) ,从两边向中间移动。

注意避免重复,本题中通过判断相邻数字相等直接跳过的方法去重,米面了使用 set容器,简单易懂。

时间复杂度:\(O(n^3)\)

参考代码

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector< vector<int> > res;
        if(nums.size() < 4) return res;
        
        sort(nums.begin(), nums.end());
        for(int i = 0; i < nums.size()-3; i++) {
            if(i > 0 && nums[i] == nums[i-1])//避免重复
                continue;
            for(int j = i+1; j < nums.size()-2; j++) {
                if(j > i + 1 && nums[j] == nums[j - 1])//再次避免重复
                    continue;

                int left = j + 1, right = nums.size() - 1;
                while(left < right ) {
                    int sum = nums[i] + nums[j] + nums[left] + nums[right];
                    if(sum < target) left++;
                    else if(sum > target) right--;
                    else {
                        res.push_back({nums[i], nums[j], nums[left], nums[right]});
                        while(left + 1 < right && nums[left+1] == nums[left])//避免重复
                            left++;
                        while(right -1 > left && nums[right-1] == nums[right])//避免重复
                            right--;
                        left++; right--;
                    }
                }
            }
        }
        return res;
    }
};

扩展

在问题讨论中看到一种效率超群的做法:7ms java code win over 100%。时间复杂度虽然也是 \(O(n^3)\),实际确实快了不少。通过将4Sum问题分解成3Sum和2Sum问题,其实就是将上述的最外两层循环分别拆成函数,添加更多的条件,可以及时判断不合理情况,从而使效率提高不少。

再深入想一想,我们见过了2Sum、3Sum和4Sum,其实可以泛化成 K-Sum 问题,找到了一篇讲的还不错的文章:k sum problem

相似题目

LeetCode 1. Two Sum
LeetCode 15. 3Sum
LeetCode 16. 3Sum Closest


LeetCode All in One题解汇总(持续更新中...)

本文版权归作者AlvinZH和博客园所有,欢迎转载和商用,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.


posted @ 2018-03-21 08:26  AlvinZH  阅读(243)  评论(0编辑  收藏  举报