分析:考察的数据结构是数组,考察的算法是查找。数组里面的查找除了二分就是双指针了。但是这里要求的是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; }