过去会遗忘,现在不会

三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 

暴力解法,三重循环找三元组,复杂度O(N3

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
if(nums.size()==3)
{
    if(nums[0]+nums[1]+nums[2]==0) ans.push_back(nums);
    return ans;
}

int begin=0;
int median=1;
int end=2;
int size=nums.size();
int count=0;
int i=0;
vector<int> ans_temp;
while(begin<size-2)
{
    if(begin!=median)
    {
        while(median<size-1)
        {
            if(median!=end)
            {
                while(end<size)
                {
                    count=nums[begin]+nums[median]+nums[end];
                    if(count==0)
                    {
                    ans_temp.push_back(nums[begin]);
                    ans_temp.push_back(nums[median]);
                    ans_temp.push_back(nums[end]);
                    sort(ans_temp.begin(),ans_temp.end());
                for(int j=0;j<ans.size();j++)
                {
                    if(ans[j]==ans_temp)
                    { ans_temp.clear();
                      break;
                    }
                }
                    if(!ans_temp.empty())
                    {
                    ans.push_back(ans_temp);
                    ans_temp.clear();
                    }
                    end++;
                    }
                    else end++;
                }
            }
            median++;end=median+1;
        }
    }
    begin++;median=begin+1;end=median+1;
}

return ans;
    }
};

时间长而且代码臃肿,一点效率都没有。

换个思路,用万能的排序(排序是真好用!!)

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> ans;
        vector<int> ans_part;
    if(nums.size()==3) 
    {
        if(nums[0]+nums[1]+nums[2]==0) ans.push_back(nums);
        return ans;
    }

sort(nums.begin(),nums.end());
int begin;int end;int count=0;

for(int i=0;i<nums.size();i++)
{
    begin=i+1;end=nums.size()-1;
    if(nums[i]>0) break;
    if(i>1&&nums[i]==nums[i-1]) continue;
    else
    {
        count=0-nums[i];
        while(begin<end)
        {
            
            if(nums[begin]+nums[end]<count)
            {
                begin++;
            }
            else if(nums[begin]+nums[end]>count)
            {
                end--;
            }
            else 
            {
                ans_part.push_back(nums[i]);
                ans_part.push_back(nums[begin]);
                ans_part.push_back(nums[end]);
                sort(ans_part.begin(),ans_part.end());
                ans.push_back(ans_part);
                ans_part.clear();
                begin++;end--;
            }
        }
    }
}

sort(ans.begin(),ans.end());
ans.erase(unique(ans.begin(),ans.end()),ans.end());

return ans;
    }
};

好像还行...至于思路,就是排序,找规律。

数组排好序了,从第一个数开始遍历,假设它大于零,那么之后的数都会大于零,就不存在三元数组。

所以只有第一个数不大于0的时候,才进行操作。

怎么操作?举个例子

这有个数组{-5,-3,-2,-1,0,1,2,3,4,5} (排好序的)

第一个数-5,剩下就要找数组内加起来是5的那俩数。这三个数位置不能相同。

那这俩数只能从-3到5这个区间找,所以设置个begin和end表示这个区间(区间有序)。

有了范围,开始找,刚开始begin=-3,end=5,begin+end=2;这说明什么?说明找小了,为了让这个和变大,只能让begin++,因为end--的话,和更小。

好,begin一路++,终于到了0这个位置,和为5,三个数找到了,存储进答案。

下面就要在区间1到4找了。一下子又找到了,再存,2,3也是,继续存,没区间了,结束当前循环。

第二个数成了-3,重复以上步骤.......

因为没有检测区间内重复的元素,所以ans里面有相同的三元组,所以在存之前排序一下,方便最后答案的去重。

--------------------------------------------------------

--------------------------------------------------------

好像还有优化空间,比如去重不用最后单独去,只要在搜索的区间加上重复元素的判定就好了。

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> ans;
        vector<int> ans_part;
    if(nums.size()==3) 
    {
        if(nums[0]+nums[1]+nums[2]==0) ans.push_back(nums);
        return ans;
    }

sort(nums.begin(),nums.end());
int begin;int end;int count=0;

for(int i=0;i<nums.size();i++)
{
    begin=i+1;end=nums.size()-1;
    if(nums[i]>0) break;
    if(i>0&&nums[i]==nums[i-1]) continue;
    else
    {
        count=0-nums[i];
        while(begin<end)
        {
            
            if(nums[begin]+nums[end]<count)
            {
                begin++;
            }
            else if(nums[begin]+nums[end]>count)
            {
                end--;
            }
            else 
            {
                ans_part.push_back(nums[i]);
                ans_part.push_back(nums[begin]);
                ans_part.push_back(nums[end]);
                sort(ans_part.begin(),ans_part.end());
                ans.push_back(ans_part);
                ans_part.clear();
                while(begin<end&&nums[begin]==nums[begin+1]) begin++;
                while(begin<end&&nums[end]==nums[end-1]) end--;
                begin++;end--;
            }
        }
    }
}
/*
sort(ans.begin(),ans.end());
ans.erase(unique(ans.begin(),ans.end()),ans.end());*/

return ans;
    }
};

 

posted on 2023-06-19 03:55  WhatAnyWay  阅读(26)  评论(0)    收藏  举报