三数之和:用Java思路分析
15. 三数之和 - 力扣(LeetCode)
第一眼思路:
看到这题我会先想到最暴力的方法———>使用三个for循环,但是仔细一想纯粹的使用for循环,时间复杂度高(O(n^3)),最关键的是,这样杂乱无章的数组数据,是无法直接通过if语句筛除重复的三元组,必须要通过哈希表进行去重。
---------------------------------------------------------------------------------------------------------------------------------
加粗为主要内容
大体框架还是三重循环,然后我选择先对数组进行排序,用Arrays.sort()或则其他排序方法都行;

因为是从小到大排序,所以我们在计算nums[start]+nums[end]时要关注和nums[i]的关系,如果大于就end--,小于就start++,等于就三下标对应的值将添加到list。因为当sta越向右数据越大,反之end越小,这就说明sta和end之间可能还有三元组,只要sta小于end,还要进行重复的操作。
接着当sta>=end时break,i++,进行第二次寻找;重复操作,直到i==nums.length-1-2结束,i没必要超过倒数第三个下标,因为sta和end相等了会break。就算不考虑这个原因,我们换位思考,当i到倒数第二个下标,那么是不是会有一个指针指向它的左边,这不就和i在左边一样吗。
现在知道大体怎么循环了,但是我们还得考虑,如果一组数据中有重复数据该怎么办?
如:-1 -1 -1 0 0 0 1 1 1 这样当i=0时另外两指针在下标1、nums.length-1和2、nums.length-1-1会出现重复三元组,同理当i=1时也会出现重复。所以只要遇到相同的元素要跳过。
有这几点我们就可以开始写代码:
public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> list = new ArrayList<>();// quickSort(nums);//快排Arrays.sort(nums);for(int i=0;i<=nums.length-1-2;i++){if(nums[i]>0) break; //当i下标指向的值都为正数,那么三数相加一定不为0if(i>0&&nums[i]==nums[i-1]) continue; //i>0是为了防止数组越界,后面与前面相同就跳出这次循环让i++int start=i+1;int end=nums.length-1;while(start<end){ArrayList<Integer> list1 = new ArrayList<>();int add=nums[start]+nums[end];if(add==-nums[i]){list1.add(nums[i]);list1.add(nums[start]);list1.add(nums[end]);list.add(list1);start++;//两指针向中靠拢--》数据大小变化你可想像一下end--;while(start<end&&nums[start]==nums[start-1]){//跳过相同大小数据start++;}while(end>start&&nums[end]==nums[end+1]){end--;}continue;}else if(add>-nums[i]){end--;}else{if(add<-nums[i]){start++;}}}}return list;}