三数之和为0

给出一个有n个元素的数组S,S中是否有元素a,b,c满足a+b+c=0?找出数组S中所有满足条件的三元组

//用数组存储数组,表示答案不唯一,不止有一个解,所以要用解集存储,解集,集
//<size时会有N个元素,<size-2时会有n-2个元素,即去掉了两个
//<size时下标止于N-1
//left<right时,最后会使left停在right的位置
//left+1<right时,会使left停在right前一个的位置
vector<vector<int>> func(vector<int>nums) {
    vector<vector<int>>res;
    sort(nums.begin(), nums.end());
    for (int i = 0; i < nums.size() - 2; i++) {
        if (i != 0 && nums[i] == nums[i - 1]) { continue; }//目标值也要去重
        //第一项一定是不重的,所以i!=0,也是为了保证i-1不会越界
        int left = i + 1, right = nums.size() - 1;
        int target = -nums[i];//三数之和为0,则移项一个,让它的相反数作为目标值,即多一个指针指向的值,来映射当前的目标值
        while (left < right) {//终止时left==right
            int sum = nums[left] + nums[right];
            if (sum > target) { right--; }
            if (sum < target) { left++; }
            if (sum == target) {
                res.push_back({ nums[i],nums[left],nums[right] });
                //考虑极端情况为左一片与右一片值都相同,且满足条件,那么会向数组中加很多组重复的数据,直到左右指针重合(此时不重合,而是交叠,因为动两个指针,left右移的同时,right左移)
                //所以需要去重,即指针遇到同一片相同的数值时,就跳过,在遇到第一个且已做处理的情况下
                //如果满足,则哪个动一下下一组都会不满足,如果不满足,那么这一组都不满足,或者使右指针动,直到满足,那么又到了前一种情况
                //即相同的数据,只要一个来判断并记录就行
                // 不需要每种情况都要去重,只要相等时就行,因为只有相等时才记录,在第一次记录后就把相同的情况全抹除
                //由于最后会有left++,right--的统一操作,所以移动指针时,不要直接越过所有,而是要指向最后一个相同的元素,即判断语句nums[left]==nums[left+1]
                //这样在left++后才可移到下一个不同的元素上
                //一般情况下只有这个判断就够了
                //但考虑极端情况,即左右的那片都相同,即合起来时一片,加起来还满足条件,那么左指针将一步冲天,直接到最后一个,再++还会越界
                //所以需要保证在这种情况下也不会出问题就需要left+1<right,才可使左右指针在正常范围内移动,
                while (left + 1 < right && nums[left] == nums[left + 1]) {//终止时left==right-1,即保证极端情况下左指针停在右指针前一个位置
                    left++;
                }
                while (right - 1 > left && nums[right] == nums[right--]) {
                    right--;
                }
                left++; right--;
            }
        }
    }
    return res;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值