分析:考察的数据结构是数组,考察的算法是查找。数组里面的查找除了二分就是双指针了。但是这里要求的是3元。那么我就用3个指针。于是用了 left ,right 作为滑动窗口,mid 在中间寻找。问题转变为如何确定是左边移动还是右边移动?即找到了这样的三元组后哪边指针移动?没找到的话和为什么情况左边移动或者右边移动?我贸然的使用了一些方法,发现总是会有漏网之🐟无法通过。于是找问题,发现我的窗口是一个在缩小的窗口。极端的请况是一边都走完了,但是错过的数据没有办法回溯,于是总是会少一部分3元组。

换换思路:本身暴力的话我需要3个大循环就可以了,假如我在外围固定一个循环,那么剩下的两个循环我换成左右指针不也是一种优化吗?于是思路换成固定一个循环,接下就可以好好的用双指针了。

本题主要考察的是双指针,一些 collection 容器相关的功能可以随便用,比如排序和去重

public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
    ArrayList<ArrayList<Integer>> res=new ArrayList<>();
    ArrayList<Integer> list=new ArrayList<>();
    if(num==null || num.length==0){
        return res;
    }
    if(num.length<3){
        return res;
    }
    Arrays.sort(num); //排序
    for(int i=0;i<num.length-1;i++){
        int left=i+1;
        int right=num.length-1;
        while(right-left>=1){
            int tmpSum=num[left]+num[right]+num[i];
            if(tmpSum==0){
                list.add(num[left]);
                list.add(num[i]);
                list.add(num[right]);
                Collections.sort(list);//排序去重
                if(!res.contains(list)){ 
                    res.add(new ArrayList(list));
                }
                list.clear();
                right--;//找到符合条件的三元组后右指针移动,其实这里左右指针都可以移动的,这里主要是把两个循环变成一个
            }else if(tmpSum<0){
                left++;
            }else {
                right--;
            }
        }
    }
    return res;
}