Skip to content

Latest commit

 

History

History
133 lines (110 loc) · 4.2 KB

15-3sum.md

File metadata and controls

133 lines (110 loc) · 4.2 KB

15. 3Sum - 三数之和

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

题目标签:Array / Two Pointers

题目链接:LeetCode / LeetCode中国

题解

首先先将数组排序,然后利用双指针进行夹逼。

对于本问题,先将数组排序,对于每个不重复的数,在其右侧的数里找两个和为该数相反数的组合,从而把问题转化为从有序数组里找和为某个值的组合。可以使用双指针夹逼,具体做法为:

ij初始为头部和尾部。当两个位置的数和为目标值时,范围向中间收缩(也就是i++,j--);如果和大于目标值,j--;如果和小于目标值,i++。直到i>=j

如何判断二元组不重复呢?只需要判断是否与最后一个一样就行。

Language Runtime Memory
cpp 120 ms 4.2 MB
class Solution {
public:
    vector<vector<int>> twoSum(vector<int>& nums, int target, int st, int ed, bool uniq) {
        vector<vector<int> > res;
        while (st < ed) {
            if (nums[st] + nums[ed] == target) {
                if (!uniq || res.empty() || res.back()[0] != nums[st]) {
                    res.push_back(vector<int>{nums[st], nums[ed]});
                }
                ++st;
                --ed;
            } else if (nums[st] + nums[ed] > target) {
                --ed;
            } else {
                ++st;
            }
        }
        return res;
    }
    
    vector<vector<int>> nSum(vector<int>& nums, int target, int st, int ed, int n, bool uniq) {
        vector<vector<int> > res;
        if (n < 1) { return res; }
        else if (n == 1) {
            if(nums.end() != find(nums.begin(), nums.end(), target)) {
                res.push_back(vector<int>{target});
                return res;
            }
        }
        else if (n == 2) {
            return twoSum(nums, target, st, ed, uniq);
        } else {
            for (int i=st; i<=ed; ++i) {
                int num = nums[i];
                if (!uniq || res.empty() || res.back()[0] != num) {
                    auto ret = nSum(nums, target-num, i+1, nums.size()-1, n-1, uniq);
                    for (auto r : ret) {
                        vector<int> tmp;
                        tmp.push_back(num);
                        tmp.insert(tmp.end(), r.begin(), r.end());
                        res.push_back(tmp);
                    }
                }
            }
            return res;
        }
    }
    
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        return nSum(nums, 0, 0, nums.size()-1, 3, true);
    }
};
Language Runtime Memory
python3 1200 ms N/A
class Solution:
    def twoSum(self, nums, target):
        res = []
        nums.sort()
        i, j = 0, len(nums) - 1
        while i < j:
            if nums[i] + nums[j] == target:
                if not res or res[-1][0] != nums[i]:
                    res.append([nums[i], nums[j]])
                i += 1
                j -= 1
            elif nums[i] + nums[j] > target:
                j -= 1
            else:
                i += 1
        return res
            
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        res = []
        nums.sort()
        tmp = set()
        for i, num in enumerate(nums):
            if num not in tmp:
                for twosum in self.twoSum(nums[i+1:], -1 * num):
                    res.append([num, twosum[0], twosum[1]])
                tmp.add(num)
        return res