高频leetcode排序部分:15. 三数之和

15. 三数之和

难度中等3966
给你一个包含 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

思路

找任意两个数的排列组合,第三个数补0(桶排序,找第三个数)

[0,0,0] 细节错误i<0 or i<=0,没有考虑到重复数字情况
[-2,0,1,1,2] 两重循环没有遍历到每个值
[82597,-9243,62390,……] -10^5 <= nums[i] <= 10^5 题目设置的值的范围不对
[0,0,……此处省略3000个0] 超时报错 if(i>0&&nums[i]==nums[i-1])设限
[34,55,79,28,46,33,2,48,31,-3,84,71,52,-3,93,15,21,-43,57,-6,86,56,94,74,83,-14,28,-66,46,-49,62,-11,43,65,77,12,47,61,26,1,13,29,55,-82,76,26,15,-29,36,-29,10,-70,69,17,49] 剪枝,剪的缺少了一部分

小技巧

去重之set,vector互换

set<vector<int>> st(res.begin(), res.end());
res.assign(st.begin(), st.end());

代码

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int i,j;
        int temp[210000]={0};
        vector<vector<int>> res;

        if(nums.size()<3)
            return res;

        sort(nums.begin(),nums.end());
        //设置桶
        for(int k=0;k<nums.size();k++)
        {
            printf("%d,",nums[k]);
            if(nums[k]>=0)
                temp[nums[k]]++;
            else
                temp[100000-nums[k]]++;//-1位于10001
        }
        printf("\n");

        //两两匹配,找桶
        for(i=0;i<nums.size();i++)
        {
            //剪枝
            if(i>0&&nums[i]==nums[i-1])
            {
                continue;
            }
            j=nums.size()-1;
            if(nums[i]<0)
            {
                temp[100000-nums[i]]--;
            }
            else
                temp[nums[i]]--;
            for(j=nums.size()-1;j>i;j--)
            {
                vector<int> a;
                // printf("%d,%d,%d\n",nums[i],nums[j],nums[i]+nums[j]);
                if(nums[j]<0)
                    temp[100000-nums[j]]--;
                else
                    temp[nums[j]]--;
                //分情况,找temp
                if((nums[i]+nums[j])>0)
                {
                    if(nums[i]+nums[j]>100000)
                        break;
                    if(temp[100000+nums[i]+nums[j]]>0)//假设结果为1,找-1
                    {
                        a.push_back(nums[i]);
                        a.push_back(nums[j]);
                        a.push_back(0-nums[i]-nums[j]);
                        sort(a.begin(),a.end());
                        res.push_back(a);
                    }
                }
                else if((nums[i]+nums[j])<0)
                {
                    if(abs(nums[i]+nums[j])>100000)
                        break;
                    if(temp[abs(nums[i]+nums[j])]>0)//假设结果为-1,找1
                    {
                        a.push_back(nums[i]);
                        a.push_back(nums[j]);
                        a.push_back(abs(nums[i]+nums[j]));
                        sort(a.begin(),a.end());
                        res.push_back(a);
                    }
                }
                else if((nums[i]+nums[j])==0&&temp[0]>0)//假设结果为-1,找1
                {
                    a.push_back(nums[i]);
                    a.push_back(nums[j]);
                    a.push_back(0);
                    sort(a.begin(),a.end());
                    res.push_back(a);
                }
                if(nums[j]<0)
                    temp[100000-nums[j]]++;
                else
                    temp[nums[j]]++;
                
            }
            if(nums[i]<0)
                temp[100000-nums[i]]++;
            else
                temp[nums[i]]++;
        }
        //去重
        set<vector<int>> st(res.begin(), res.end());
        res.assign(st.begin(), st.end());
        return res;
    }
};
上一篇:【编程技巧】无锁并发之原子操作CAS


下一篇:c++高精度一系列的算法(包含阶乘求和)