LeetCode.M15.三数之和

LeetCode.M15

题目:

在这里插入图片描述

题目大意:

​ 如图所示。

数据范围:

如图所示

思路:

​ 排序+双指针。首先明确题目要求答案不允许重复。如何保证这一点呢?假设我们有一个数组nums:a1 a2 a3 b1 b2 b3 c1c2 c3 d1 d2 d3 ,其中a + b + c = 0。

  • 第一重循环枚举first时,首先first = a1,又知后面存在b、c使得 a + b + c = 0,则(a1,b,c)为一个答案,但是第一个a后面还有两个a,这两个a都会和后面的b、c组成一个答案,造成了重复,所以,在枚举first时,我们要求这次的first和上一次循环的firt不同,所以在处理完第一个a时,跳过其后面两个a,直接开始处理第一个不等于它前面元素的值b,此时first = b。这样就保证了firts不重复。
  • 第二重循环枚举second,与枚举first同理,处理的是first后的第一个元素,或者是不等于它前一个元素值的元素,这样就保证了second不重复。由于third = -(first + second), 这样也保证了third不重复。
  • 那么如何找到third呢?我们可以使用双指针,假设现在first = a1, 令target = -a1,second = a2, 在第二重循环中固定住second,则我们需要找到一个third满足 second + third = target, 初始时,令左指针l为a2的下标,右指针r为d3(可能的third值x)的下标,如果a2 + x > target,我们不断移动右指针,在l < r 的情况下,找到第一个使a2 + x <= target的 x。
    • 如果 a2 + x == target 了,则说明找到了一个合法解,将(first(a1),second(a2), x)加入答案中。
    • 如果 a2 + x < target,不需要向右移动r了,因为越向右移动x越小,此时我们应该去处理下一个second(b1,跳过了a3),这样才有可能使second + third = target。注意不需要将右指针重新赋为len - 1,因为下一个second(b1)的值肯定比此次second(a2)的值要大,为了满足second + third = target ,相应的third的值也会更小)。
    • 如果右指针一直向左移动到l == r了,则说明找不到使a2 + x <= target的 x,该first找不到一个second和third,则继续遍历下一个first(b1)

代码:

import java.util.*;

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> lists = new ArrayList<>();
        int len = nums.length;
        Arrays.sort(nums);
        for (int first = 0; first < len; first ++ ){
            if (first > 0 && nums[first - 1] == nums[first])
                continue;
            int target = -nums[first], third = len - 1;
            for (int second = first + 1; second < len; second ++ ){
                if (second > first + 1 && nums[second - 1] == nums[second])
                    continue;
                while (second < third && nums[third] + nums[second] > target){
                    third -- ;
                }
                if (second == third)
                    break;
                if (nums[third] + nums[second] == target){
                    List<Integer> list = new ArrayList<>();
                    list.add(nums[first]);
                    list.add(nums[second]);
                    list.add(nums[third]);
                    lists.add(list);
                }
            }
        }
        return lists;
    }
}
public class Main {
    public static void main(String[] args) {
        Solution solution = new Solution();
//        int[] nums = new int[]{-1,0,1,2,-1,-4};
        int[] nums = new int[]{-1, 0, 1, -1, 0, 1};
        System.out.println(solution.threeSum(nums).toString());
    }

}

时空复杂度分析等:

  • 时间复杂度 : O(n^2)

  • 空间复杂度 : 排序的空间复杂度

题目链接:

15. 三数之和 - 力扣(LeetCode)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值