LeetCode 15.三数之和(c++)

123 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第11天,点击查看活动详情

前言

从零开始学习c++,每天起码做一道leetcode题目,在此记录,希望最后能够有所收获!

一、题目描述

15.三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != 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

二、思路分析

这是一道中等难度的题目,给定一个数组,要求你找出该数组中所有三个序号不相等且相加等于0的数,并返回一个二元数组。特别值得注意的是返回的三个数不能相同。这也是这个题目中最难的一个地方。为此需要在程序中做出诸多的限制。

在最开始看到题目的时候,我首先想到的就是排序。先将数组中的数字进行排序,再去掉其中重复的元素。最后再去寻找符合题目要求的i,j,k。然而这样实在是过于复杂了,我思来想去,是否能用双指针呢?但这个题目要求ijk三个量,似乎不可以哎。

最后看了一些高赞的思路,还是得用双指针。同样,先要观察根据题目的要求数组会有哪些规律出现。在该题目中,我们必须要注意重复的元素,但它们在数组中的位置是不确定的。所以排序是必要的。同时,在排好序后,可以设定i<j<k,此时,将i进行遍历,nums[i]应该小于0,否则不可能满足题意。

三、AC代码

class Solution{
public:
	vector<vector<int>> threeSum(vector<int>& nums){
		int k;
        vector<vector<int>> ans;
    sort(nums.begin(),nums.end());
    for(int i=0;i<nums.size();i++)
    {
        if(i>0 && nums[i]==nums[i-1])
        {
            continue;
        }
        k = nums.size() - 1;
        for (int j = i + 1; j < k;j++)
        {
            if(j>i+1 && nums[j]==nums[j-1])
            {
                continue;
            }
            while(nums[i]+nums[j]+nums[k]>0 && j<k)
            {
                k--;
            }
            if(j == k) break;
            if(nums[i]+nums[j]+nums[k]==0)
            {            
                ans.push_back({nums[i], nums[j], nums[k]});
            }  
        }
    }
		return ans;
	}
};

提交排名

image.png

四、总结

这道题目应该是我目前遇到的最难的题目了,同样巧妙的考验了双指针。但其中的逻辑更加复杂了。应该仔细地理清楚,确保下次能够做出来。