写在前面,参考力扣官网的画解算法。。真的太清晰明了了
一、java代码
/*
* @lc app=leetcode.cn id=15 lang=java
*
* [15] 三数之和
*/
// @lc code=start
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
//ans接收答案
List<List<Integer>> ans=new ArrayList();
//给定nums数组长度
int len=nums.length;
//当给定数组为空或者长度小于3则直接返回ans
if(nums==null||len<3) return ans;
//首先对数组进行排序
Arrays.sort(nums);//排序
//固定i
for(int i=0;i<len;i++){
//后面的也会大于0 ,所以在此处终结
if(nums[i]>0) break;//如果当前数字大于0,则三数之和必定大于0,结束循环
//返回for循环,i++
if(i>0&&nums[i]==nums[i-1]) continue;//去重
//使用左右指针指向nums[i]后面的两端
int L=i+1;
int R=len-1;
//当L<R时才能继续下面的判断,否则i++
while(L<R){
//核心公式
int sum=nums[i]+nums[L]+nums[R];
//当sum==0是,左加右减收缩
if(sum==0){
//将当前结果存到ans中
ans.add(Arrays.asList(nums[i],nums[L],nums[R]));
//当`sum==0`时,`nums[L]==nums[L+1]`,则会导致结果重复,应该跳过,`L++`
while(L<R && nums[L]==nums[L+1]) L++;//去重
//当`sum==0`时,`nums[R]==nums[R-1]`,则会导致结果重复,应该跳过,`R--`
while(L<R && nums[R]==nums[R-1]) R--;//去重
//左加右减
L++;
R--;
}
else if(sum<0) L++;
else if(sum>0) R--;
}
}
return ans;
}
}
// @lc code=end
二、解题思路
1、首先对数组进行排序
,排序后固定一个数nums[i]
2、再使用左右指针,指向nums[i]
后面部分的两端
,数字分别为nums[L]
和nums[R]
3、计算三个数的和sum
,判断是否满足为0,满足则添加进结果集ans
(1)如果nums[i]
大于0
,则三数之后必然无法大于0,结束循环
(2)如果nums[i]==nums[i-1]
,则说明该数字重复,会导致结果重复,所以跳过
(3)当sum==0
时,nums[L]==nums[L+1]
,则会导致结果重复,应该跳过,L++
(4)当sum==0
时,nums[R]==nums[R-1]
,则会导致结果重复,应该跳过,R--
三、图解
(1/12)
(2/12)
(3/12)
(4/12)
(5/12)
(6/12)
(7/12)
(8/12)
(9/12)
(10/12)
(11/12)
(12/12)