【LeetCode】No.15. 3Sum -- Java Version

本文介绍了如何使用两种不同的算法解决LeetCode中的三数之和问题。第一种方法是穷举法,遍历所有可能的三元组并去除重复。第二种方法是将3Sum转换为2Sum,通过排序和双指针优化,降低时间复杂度到O(n^2)。这两种方法都在考虑效率和去重策略上进行了优化。

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

题目链接: https://leetcode.com/problems/3sum/

1. 题目介绍(三数之和)

Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.

【Translate】: 给定一个整数数组nums,返回所有的三元组[nums[i], nums[j], nums[k]],使得i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0。

Notice that the solution set must not contain duplicate triplets.

【Translate】: 注意,解决方案集中不能包含重复的三元组。

【测试用例】:
test1
【约束】:
Constraints

2. 题解

2.1 穷举再去重 – O(n3)

  该题解遍历所有元素,只要满足nums[i] + nums[j] + nums[k] == 0的条件式,就被存入listAll,遍历完毕之后,我们再对listAll进行去重操作。

    private static boolean checkDifferent(List<Integer> list, List<Integer> list1) { 
        Collections.sort(list);
        Collections.sort(list1);
        // System.out.println(list.toString().equals(list1.toString()));
        return list.toString().equals(list1.toString());
    }

    
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> listAll = new ArrayList<List<Integer>>();
        
        for (int i = 0; i < nums.length; i++)
        {
            for (int j = i+1; j < nums.length; j++)
            {
                for (int k = j+1; k < nums.length; k++)
                {
                    if(nums[i] + nums[j] + nums[k] == 0)
                    {
                        List<Integer> list = Arrays.asList(nums[i], nums[j], nums[k]);
                        listAll.add(list);
                    }
                }
            }
        }
        
        for (int i = 0; i < listAll.size()-1; i++){
            for(int j = i+1; j < listAll.size(); j++){
                if(checkDifferent(listAll.get(i), listAll.get(j)))
                {
                    listAll.remove(j);
                    j--;
                }
            }

        }
        
        return listAll;
        
    }

case1

2.2 3sum convert to 2sum – O(n2)

  shpolsky在Discuss中提供的解法,目前在Java Most Vote中排名第一。他的思想是对输入数组排序,然后遍历三元组中可能的第一个元素的所有下标。对于每个可能的第一个元素,都对数组的其余部分进行标准的双向2Sum扫描。此外,他们希望跳过相等的元素,以避免在答案中出现重复,而不生成集合或类似的smth。
  该题解的核心思想是将3sum问题转变成了2sum问题,然后通过左右指针去解决问题。

public List<List<Integer>> threeSum(int[] num) {
    Arrays.sort(num);
    List<List<Integer>> res = new LinkedList<>(); 
    for (int i = 0; i < num.length-2; i++) {
        if (i == 0 || (i > 0 && num[i] != num[i-1])) {  // 初步排除重复元素
            int lo = i+1, hi = num.length-1, sum = 0 - num[i];
            while (lo < hi) {
                if (num[lo] + num[hi] == sum) {
                    res.add(Arrays.asList(num[i], num[lo], num[hi]));
                    while (lo < hi && num[lo] == num[lo+1]) lo++;
                    while (lo < hi && num[hi] == num[hi-1]) hi--;
                    lo++; hi--;
                } else if (num[lo] + num[hi] < sum) lo++;
                else hi--;
           }
        }
    }
    return res;
}

// 改进之处
// 1. 由于一开始我们就对num数组进行了排序,那么在一开始我们就可以判断num[i]是否大于0,如果大于0直接结束循环,没有答案,可以省下一部分时间。
 if(num[i] > 0){
       break;
   }
// 2. i>0判断冗余,可以直接去掉

case2

3. 可参考

[1] java List一次性添加多个元素
[2] 关于java:如何一次向arraylist添加多个值?
[3] Java如何判断两个集合的元素是否完全相等
[4] Java 之 List<List>
[5] List集合的各种排序
[6] 【Video】3 Sum & 4 Sum (Generalized for k sum) | LeetCode 15 | LeetCode 18 | Medium

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TomLazy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值