leetcode 15.三数之和

发布时间 2024-01-12 12:00:17作者: 米乡卷炸粉

leetcode 15.三数之和

第十五题:三数之和

1.排序 + 双指针:

和两数之和不同,但可以转化为类似的思路,即确定一个数,去找数组中是否有另外两个数之和等于它的相反数。本题的难点在于如何去除重复解,如果是无序数组,则需要对每个值所在的位置进行记录并进行比较。但如果是有序数组且相加结果为0,那么对于当第一个指针指向的位置大于0后,后序位置相加不可能为0,降低了复杂度。还要注意的是,遍历中会遇到值相同的元素,由于本题只要结果,遇到这样的元素应该跳过。

算法流程:
1.特判,对于数组长度 n,如果数组为 null 或者数组长度小于 3,返回 null。

2.对数组进行排序。

3.遍历排序后数组: 若 nums[i]>0:因为已经排序好,所以后面不可能有三个数加和等于 0,直接返回结果。
对于重复元素:跳过,避免出现重复解
令左指针 L=i+1,右指针 R=n−1,当 L<R时,执行循环:
当nums[i]+nums[L]+nums[R]==0,执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 L,R 移到下一位置,寻找新的解
若和大于 0,说明 nums[R] 太大,R 左移
若和小于 000,说明 nums[L] 太小,L 右移

复杂度分析:
时间复杂度:O(n^2)
空间复杂度:O(1)

public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        if (nums == null || nums.length < 3) return null;
        Arrays.sort(nums);
        int n = nums.length;
        for (int i =0;i<n;i++){
            
            if (nums[i] > 0) return result;
            if (i>0 && nums[i] == nums[i-1]) {
                continue;
            }
            int left = i+1;
            int right = n-1;
            while (left<right){
                if (nums[i] + nums[left] + nums[right] == 0){
                    List<Integer> temp = new ArrayList<>();
                    temp.add(nums[i]);
                    temp.add(nums[left]);
                    temp.add(nums[right]);
                    result.add(temp);
                    while (left < right && nums[left] == nums[left+1]) left+=1;
                    while (left < right && nums[right] == nums[right - 1]) right-=1;
                    left+=1;
                    right-=1;
                }
                else if (nums[i] + nums[left] + nums[right] > 0) {
                    right-=1;
                }
                else left+=1;
            }
        }
        return result;
    }