LeetCode刷题笔记:Leetcode15. 3Sum

问题描述:


在这里插入图片描述

个人思路


自己第一遍写

题目要求在一个数组中找到所有包含三个不同位置的元素且和为0的组,且要求这些组中不能出现元素相同的组。

因此数据结构上明显使用数组,而数组的基本操作有排序和遍历。(做题的时候题干给出的输出让我以为不能对原始数组进行排序,所以没用双指针等办法,直接遍历了。遍历时间复杂度 O 3 O^3 O3 太高了,再结合遍历临时数组,直接给干到 O 6 O^6 O6 去了,纯纯反例)

根据要求取三个变量作为index来遍历整个数组,i、j、k、的大小和顺序保证了在考虑顺序的情况下不会多次记录同一个组。

但是题目要求是不出现包含相同元素的组,一开始我打算用 ASCLL 码值相加来判断两个组是否包含相同元素,但是意识到如果输入数组为两位数就不行了,比如:{-21,0,21}和{-12,0,12}。

同时题干给出的输出让我以为不能对原始数组进行排序,因此我使用了一个临时数组,将所有已产生的三元数组排序之后都放进去,新产生的三元数组在排序之后与已有的进行比较,若不重合,则加入结果数组中。


对比博客答案之后的思路

在可以对数组进行排序的基础上,使用双指针法。双指针法在数组从小到大的基础上,选定最左边的作为基准 a[i],取 i+1 和 n 作为两个指针

  • 当 -a[i] < a[i+1] + a[n] 时,说明大了,右边指针反为 n - 1。这时,有可能 a[n-1] == a[n], 但是在循环判断之下,会保持 a[i+1] 不变一直 n–,直到 -a[i] ==
    a[i+1] + a[n] 或者 -a[i] > a[i+1] + a[n] ,避免了重复。
  • 当 -a[i] > a[i+1] + a[n] 时,情况相反
  • 当 -a[i] == a[i+1] + a[n] 时,取三个值作为一个组,然后让 i++ 到 左指针 !=a[i++]

遍历结束之后 a[i] 要右移到下一个不同的数。数组从小往大排,出现过的a[i] 就不会再出现了,保证了得出的三元数组的唯一性

这样 排序为 O ( n l o g n ) O(nlog n) O(nlogn) ,外层选 a[i] 为 O(n),内层指针比较也为 O(n),最后时间复杂度为 O ( n 2 ) O(n^2) O(n2)

网上大佬的思路


https://zhuanlan.zhihu.com/p/104800339

我的代码


public class threeSumSolution {  
    public static List<List<Integer>> threeSum(int[] nums) {  
        List<List<Integer>>  outPut = new ArrayList<>();  
        List<List<Integer>>  tempArray = new ArrayList<>();  
        if (nums.length < 3) {  
            System.out.println ("enter can't less than 3");  
        } else if (nums.length == 3) {  
            int sum = 0;  
            List<Integer> result = new ArrayList<Integer>();  
            for (int a : nums){  
                sum += a;  
                result.add(a);  
            }  
            System.out.println ("The only possible triplet does not sum up to " + sum);  
            if (sum == 0) {  
                outPut.add(result);  
            }  
        } else {  
            for (int i = 0; i < nums.length - 2; i++) {  
                for (int j = i + 1; j < nums.length - 1; j++){  
                    for (int k = j + 1; k < nums.length ; k++){  
                        if ( (nums[i] + nums[j] + nums[k]) == 0) {  
                            List<Integer> result = new ArrayList<Integer>();  
                            List<Integer> tempResult = new ArrayList<Integer>();  
                            result.add(nums[i]);  
                            result.add(nums[j]);  
                            result.add(nums[k]);  
                            System.out.println("nums[" + i + "] + nums[" + j + "] + nums[" + k + "] = " + (nums[i] + nums[j] + nums[k]));  
                            tempResult = result;  
                            tempResult.sort(Integer::compareTo);  
                            boolean found = false;  
                            for (List<Integer> e : tempArray){  
                                if (e.equals(tempResult)){  
                                    found = true;  
                                    break;  
                                }  
                            }  
                            if (!found){  
                                tempArray.add(tempResult);  
                                outPut.add(result);  
                            }  
  
                        }  
                    }  
                }  
            }  
        }  
        System.out.println(outPut.toString());  
        return outPut;  
    }  
    public static void main(String[] args){  
        int[] input = {-1,0,1,2,-1,-4};  
        List<List<Integer>>  outPut = threeSum(input);  
    }  
}
  • 22
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值