leetcode—数组—三数之和

三数之和

题目类型:数组
题目来源: leetcode传送门

给你一个包含 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
* -10^5^ <= nums[i] <= 10^5^

方法一:

最暴力的方法,三重循环,但是需要注意的细节是,由于答案不能重复,也就是避免[-1,0,1]和[-1,1,0]这种情况出现,要做的首先就是排序了,排序之后考虑如何避免这种情况的出现。如果第p次第一层循环变量为i,那么在第p+1次,第一层的循环变量i+1,这时如果排好序的nums[i]和nums[i+1]相等,则第二三层循环就可以仍然在上一次得到答案的状态下再次得到答案,自然就会出现重复的答案。需要做的就是在第p+1次时的vector中的元素与第p次的元素不能相同。这样就可以完成去重的过程了。代码如下(由于是O(n3)的,所以超时了):

vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int> > ans(0);
        vector<int> t_vector(0);
        sort(nums.begin(), nums.end());

        for(int i = 0; i < nums.size(); i ++)
        {
            if(!(i == 0 || nums[i] != nums[i-1]))
                continue;
            for(int j = i + 1; j < nums.size(); j ++)
            {
                if(!(j == i+1 || nums[j] != nums[j-1]))
                    continue;
                for(int k = j + 1; k < nums.size(); k ++)
                {
                    if(!(k == j+1 || nums[k] != nums[k-1]))
                        continue;
                    if(nums[i] + nums[j] + nums[k] == 0)
                    {
                        t_vector.clear();
                        t_vector.push_back(nums[i]);
                        t_vector.push_back(nums[j]);
                        t_vector.push_back(nums[k]);
                        ans.push_back(t_vector);
                    }
                }
            }
        }
        return ans;
    }

方法二:

采用双指针的做法,第一重循环不变,在第一重循环内部,j指向i+1,k指向nums.size()-1,如果nums[i]+nums[j]+nums[k]等于0,则记录,并且向右移动j指针,如果大于0,则向左移动k指针,如果小于0,则向右移动j指针,这里的移动都要满足移动之后与上一次指的位置的指不同。
代码如下:

vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int> > ans(0);
        sort(nums.begin(), nums.end());

        for(int i = 0; i < nums.size(); ++i)
        {
            if(!(i == 0 || nums[i] != nums[i-1]))
                continue;
            int j = i + 1;
            int k = nums.size() - 1;
            int tar = 0 - nums[i];
            while(j < k)
            {
                if(nums[j] + nums[k] == tar)
                {
                    ans.push_back({nums[i], nums[j], nums[k]});
                    while(j < k && nums[j+1] == nums[j])
                        ++j;
                    ++j;
                }
                else if(nums[j] + nums[k] > tar)
                {
                    while(j < k && nums[k-1] == nums[k])
                        --k;
                    --k;
                }
                else if(nums[j] + nums[k] < tar)
                {
                    while(j < k && nums[j+1] == nums[j])
                        ++j;
                    ++j;
                }
            }
        }
        return ans;
    }
    }

作答加上写博客,一共用了接近1.5个小时,还是太慢了,还需要继续练习呀!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值