js
/**
* @param {number[]} nums
* @return {number[][]}
*/
var threeSum = function(nums) {
nums=nums.sort((a, b) => a-b);
let len = nums.length
// 如果长度不足3, 或者排序后最小值>0、或者最大值小于0, 不符合要求
if(len<3 || nums[0]>0 || nums[len-1]<0) return [];
if(nums[0]===0 && nums[len-1]===0) return [[0,0,0]]
let res = []
// 只有 numx[fixed]<=0,才可能出现答案
for(let fixed=0; nums[fixed]<=0; fixed++){
// 在比固定数字大的区域开启双指针
let left = fixed+1, right = len-1;
while(left < right){
// 检验当前位置的三数之和是否满足题意
let sum = nums[fixed] + nums[left] + nums[right]
if(sum < 0){
// 和 < 0, 则左指针指向的较小值增大,
left++
// 同时注意跳过重复值
while(left<right && nums[left]===nums[left-1]){
left++
}
}else if(sum > 0){
// 和 > 0, 则右指针指向的较大值减小
right--
// 同时注意跳过重复值
while(left<right && nums[right]===nums[right+1]){
right--
}
}else{
// 满足条件
res.push( [nums[fixed], nums[left], nums[right]] )
// 先各走一步
left++, right--
// 若左指针当前数据和上一个数据相等, 则指针右移
// 不能和下一个比较, 因为可能存在当 left===right+1时有nums[left]===nums[right]&&sum===0
// 如果和方向相同的下一个比较,直接就把这种情况跳过了
while(left<right && nums[left]===nums[left-1]){
left++
}
while(left<right && nums[right]===nums[right+1]){
right--
}
}
}
// 一个nums[fixed]检验完毕后, 跳过重复的值
while(nums[fixed] == nums[fixed+1]) fixed++
}
return res;
};