Hot100-Day26-T15三数之和

0 阅读2分钟

Day26[26/3/26]T15三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

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

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1][-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0

提示:

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

解题思路

  1. 先排序,因为排序之后才能用双指针快速搜索两个数字
  2. 先固定好第一个数字 nums[i] 然后目标就是找到两个数,和为 -nums[i]
  3. 用双指针找到剩下的两个数字
  4. 这里你需要注意的就是,因为输出结果要求去重,所以你在搜索的时候,遇到重复元素就需要跳过

双指针法:

首先你对一个数组进行排序,然后左指针最左,右指针最右。

然后求取 sum,对比目标值,如果 sum 大了,那么右指针左移,如果小了则左指针右移,如果相等,那么就是找到结果了,然后随意移动一个指针寻找下一个即可。

循环条件就是左右指针没有相遇。

Code

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class Solution
{
public:
    vector<vector<int>> threeSum(vector<int> &nums)
    {
        vector<vector<int>> result;
        // 1. 先排序
        sort(nums.begin(), nums.end());
        // 2. 遍历固定第一个数字

        for (int i = 0; i + 2 < nums.size(); i++)
        {
            // 如果和上次一样,那么就要跳过,防止重复
            if (i && nums[i - 1] == nums[i])
            {
                continue;
            }

            // 3. 双指针搜索
            int target = -nums[i];
            int left = i + 1;
            int right = nums.size() - 1;
            while (left < right)
            {

                // 双指针逻辑
                int sum = nums[left] + nums[right];
                if (sum > target)
                {
                    right--;
                }
                else if (sum < target)
                {
                    left++;
                }
                else
                {
                    // cout << " i, left, right :" << i << left << right << endl;
                    // 4. 出现答案,记录下并且继续搜索
                    result.push_back({nums[i], nums[left], nums[right]});
                    left++;

                    // 这里进行去重,只需要确保左指针指向的值变化了就行
                    while (left < nums.size() && nums[left] == nums[left - 1])
                    {
                        left++;
                    }
                }
            }
        }

        return result;
    }
};

auto main() -> int
{
    // vector<int> nums{-1, 0, 1, 2, -1, -4};
    vector<int> nums{0, 0, 0, 0};

    Solution sol;

    vector<vector<int>> result = sol.threeSum(nums);

    for (const auto &row : result)
    {
        cout << "[ ";
        for (const auto &index : row)
        {
            cout << index << ",";
        }
        cout << " ]" << endl;
    }
}