[LeetCode 15.] 三数之和

LeetCode 15. 三数之和

题目描述

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

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

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]

示例 2:

输入:nums = []
输出:[]

示例 3:

输入:nums = [0]
输出:[]

提示:

  • 0 <= nums.length <= 3000
  • -105 <= nums[i] <= 105

解题思路

经典双指针问题。
也可以用哈希,注意去重和三元组中重复元素的问题。哈希更慢,因为有元素重复问题需要处理,还有额外空间开销。

参考代码

双指针

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        if (nums.size() < 3) return {};
        sort(nums.begin(), nums.end()); // for unique result
        if (nums[0] > 0) return {};
        vector<vector<int>> res;
        size_t n = nums.size();
        for (size_t i =0; i<n; i++) {
            if (i > 0 && nums[i-1] == nums[i]) continue; // 去重
            size_t j = i+1;
            size_t k = n-1;
            while (j < k) {
                if (nums[i] + nums[j] + nums[k] < 0) {
                    j++;
                } else if (nums[i] + nums[j] + nums[k] > 0) {
                    k--;
                } else {
                    if (!(j > i+1 && nums[j-1] == nums[j]
                        && k < n-1 && nums[k] == nums[k+1])) { //  去重
                        // 有序 nums[i] <= nums[j] <= nums[k]
                        res.push_back({nums[i], nums[j], nums[k]});
                    }
                    j++;
                    k--;
                }
            }
        }
        return res;
    }
};

排序+哈希

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        if (nums.size() < 3) return {};
        sort(nums.begin(), nums.end()); // for unique result
        if (nums[0] > 0) return {};
        unordered_map<int,int> cnt;// <num, cnt>
        for (int x : nums) {
            cnt[x]++;
        }
        vector<vector<int>> res;
        size_t n = nums.size();
        for (size_t i =0; i<n; i++) {
            if (i > 0 && nums[i-1] == nums[i]) continue; // 去重
            for (size_t j=i+1; j<n; j++) {
                if (j > i+1 && nums[j-1] == nums[j]) continue; // 去重
                int x = nums[i] + nums[j];
                // if (cnt[-x] && nums[j] <= -x) { // 有序
                if (nums[j] > -x) continue;
                if ((cnt[-x] >= 1 && nums[j] < -x)
                    || (cnt[-x] >= 2 && nums[i] < nums[j] && nums[j] <= -x)
                    || (cnt[-x] >= 3 && nums[i] == -x)) { // 有序
                    res.push_back({nums[i], nums[j], -x});
                }
            }
        }
        return res;
    }
};
posted @ 2021-08-14 18:35  与MPI做斗争  阅读(36)  评论(0编辑  收藏  举报