LeetCode OJ 15 3Sum [Medium]

本文探讨了在给定整数数组中寻找三个数相加为零的所有唯一组合的问题,并提供了一种有效的解决方案。通过先排序再使用双指针技巧避免重复组合,实现了O(n^2)的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

Given an array S of n integers, are there elements a, b,c in S such that a + b + c = 0? Find all unique triplets in the array whichgives the sum of zero.

Note: The solution set must not contain duplicatetriplets.

For example, given arrayS = [-1, 0, 1, 2, -1, -4],

A solution set is:

[ [-1, 0, 1],[-1, -1, 2]]

题目理解:

    给定n个整数组成的Array,是否这n个整数中存在a+b+c==0,如果存在则输三元组[a,b,c];三元组[a,b,c]不能重复即保证三元组是唯一的;三元组[a,b,c]不能降序排列。

测试用例:

1.  功能测试:S = [-1, 0, 1, 2, -1, -4],全0,全1;

2.  边界测试:S中的整数个数小于3

3.  错误测试:S是null

分析:

1.   用三重循环,时间复杂度太高,要思考其他的方法;

2.   先将S排序;

3.   数字a从S[0]到S[n-2]开始循环:

4.   保证a不重复,即a不等与它前面一个数字S[i]!=S[i-1]

5.   设置lo、hi指针,lo从a的后面以为开始,hi从数组最末尾开始;

6.   判断a+S[lo]+S[hi]是否等于0,如果等于0则,则找到一组数字,将指针lo向后移动,将hi向前移动;

7.   如果S[lo]+S[hi]<-a,则lo往后移动

8.   如果S[lo]+S[hi]>-a,则hi往前移动

9.   直到lo>=hi时,不再移动lo和hi指针,a取下一个数字开始下一轮计算

10. 容易出错的地方在于如何保证b,c不重复:在找到一组数字后,移动lo和hi,跳过相同的S[lo]和S[hi];没有找到一组数字,移动lo后,判断是否与之前的相同,跳过相同的S[lo],移动hi后,判断是否与之前的相同,要跳过相同的S[hi]

11. 跳过相同的数字代码:while (lo< hi && nums[lo] == nums[lo - 1]) lo++;
               
while (lo< hi && nums[hi] == nums[hi + 1]) hi--;
要注意这两行代码的位置

我的解答:

public List<List<Integer>> threeSum(int[] nums) {
    List<List<Integer>> ans =new ArrayList<>();
    if (nums.length < 3) return ans;
    Arrays.sort(nums);
    for(int i = 0;i < nums.length - 2; i++) {
        if (nums[i]> 0){
            return ans;
        }
        if (i> 0 &&nums[i] == nums[i - 1]) continue;
        int target= -nums[i];
        int lo = i+ 1,hi = nums.length - 1;
        while (lo< hi) {
            if (nums[lo]+ nums[hi] == target) {
                ans.add(Arrays.asList(nums[i],nums[lo], nums[hi]));
                lo++;
                hi--;
                while (lo < hi && nums[lo] == nums[lo - 1])lo++;
                while (lo < hi && nums[hi] == nums[hi + 1])hi--;
            }
            else if (nums[lo]+ nums[hi] < target) {
                lo++;
                while (lo < hi && nums[lo] == nums[lo - 1])lo++;
            }
            else {
                hi--;
                while (lo < hi && nums[hi] == nums[hi + 1])hi--;
            }
        }
    }
    return ans;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值