题解 | #三数之和#

三数之和

https://www.nowcoder.com/practice/345e2ed5f81d4017bbb8cc6055b0b711

2022.0819算法第38题三数之和
这道题感觉挺麻烦的的,难度还可以就是复杂,细节点比较多。
首先思路还是挺简单的,采用双指针算法,先固定a,然后在剩余的数字中选择b和c,b和c通过向中心移动
逐步缩小范围,获取最终的结果。
算法有的点是需要去重的,结果中不能有重复的三元组,这点就需要做许多判断。
首先对数组进行排序,后面的判断依据就是根据有序的数组进行的。
(不能直接去除重复元素,这样会丢失解)
sort(num.begin(),num.end());
固定第一个元素a,遍历整个数组
for(int i=0;i<num.size();i++)
判断当前值是否大于零,如果大于零,则后面就没有能够相加为零的组合,直接跳出,(数组有序)
if(num[i]>0)
    break;
对a重复的情况进行判断,如果当前值与前一个相同,则当前值就不需要在寻找,
如{-2,-2,-1,3},第一次能找到{-2,-1,3},当循环到第二个-2时也会得到这个结果
因此需要将重复的结果去除。
if(i>0&&num[i]==num[i-1])
    continue;
之后需要初始化左右两个指针,都是对当前值的后面所有元素进行搜索,当前值前面的已经搜索过了,不需要考虑。
int left=i+1;
int right=num.size()-1;
之后需要一直遍历left和right两者的值,条件为
while(right>left)
两者逐渐向中间靠拢,两个指针移动的条件为三者之和的大小,这也是进行排序的原因
if(num[i]+num[left]+num[right]>0)
    right--;
else if(num[i]+num[left]+num[right]<0)
    left++;
else{
    res.push_back({num[i],num[left],num[right]});    
    right--;
    left++;
    while(left<right&&num[right]==num[right+1])
        right--;
    while(left<right&&num[left]==num[left-1])
        left++;

}                                      
这里面需要考虑的也很多
首先,当三者之和大于0时,右指针左移;小于0时,左指针右移;
当三者之和等于0时,加入答案,但此时也需要考虑左指针前面和右指针后面元素相等的问题。
例如{-1,-1,-1,0,1,1,1}
当left=1,right=6时,有结果{-1,-1,2}
然后两者同时向中间移动,
left=2,right=5,此时结果也是{-1,-1,2}
因此需要将重复的结果进行去除
通过判断左指针和前一个是否相等,右指针是否和后一个相等,
while(left<right&&num[right]==num[right+1])
    right--;
while(left<right&&num[left]==num[left-1])
    left++;
直到找到不相等的结果在进行存储。
总而言之这个好理解,但是不好写。






#算法题#
全部评论

相关推荐

有趣的牛油果开挂了:最近这个阶段收到些杂七杂八的短信是真的烦
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务