题目描述

解题思路
通过 排序 + 双指针 高效解决:
- 排序预处理:将数组升序排序,便于后续去重和双指针操作
- 固定第一个数 :遍历数组,固定当前数字
nums[i]
作为三元组的第一个元素 - 双指针搜索 :
- 左指针
left = i+1
,右指针right = len-1
- 计算目标值:
target = -nums[i]
- 移动左右指针:
- 若
nums[left] + nums[right] == target
→ 找到一组解 - 若和小于
target
→ 左指针右移(增大数值) - 若和大于
target
→ 右指针左移(减小数值)
- 若
- 左指针
- 关键去重 :
- 跳过重复的
nums[i]
(固定值去重) - 找到解后跳过重复的
nums[left]
和nums[right]
(双指针去重)
- 跳过重复的
代码实现
java
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
int length=nums.length;
List<List<Integer>> result=new ArrayList<>();
for(int i=0;i<length;i++){
if(i>0&&nums[i]==nums[i-1]){
continue;
}
int left=i+1;
int right=length-1;
int target=0-nums[i];
while(left<right){
if(nums[left]+nums[right]==target){
result.add(List.of(nums[i],nums[left],nums[right]));
left++;
right--;
while(left<right&&nums[left]==nums[left-1]){
left++;
}
while(left<right&&nums[right]==nums[right+1]){
right--;
}
}
else if(nums[left]+nums[right]<target){
left++;
}else{
right--;
}
}
}
return result;
}
算法解析
-
排序预处理(时间复杂度 O(n logn))
- 使相同数字相邻,便于后续去重操作
- 使双指针搜索成为可能(利用有序性)
-
固定值去重(关键步骤)
- 确保相同的
nums[i]
只处理一次 - 从
i>0
开始判断避免越界
-
双指针搜索(时间复杂度 O(n²))
- 核心逻辑 :固定
i
后,问题转化为两数之和问题 - 指针移动 :
sum < target
:左指针右移(增大数值)sum > target
:右指针左移(减小数值)
- 核心逻辑 :固定
-
解去重处理(关键步骤)
- 找到解后立即跳过重复的左右指针值
- 确保不会记录重复的三元组
复杂度分析
- 时间复杂度 :O(n²) 排序 O(n logn) + 双指针搜索 O(n²) → 主导项为 O(n²)
- 空间复杂度 :O(1) 除结果集外,只使用常数级额外空间(排序占用 O(logn) 栈空间,不计入额外空间)
边界与陷阱
- 输入边界 :
- 数组长度小于 3 直接返回空集
- 全正数/全负数数组无解
- 去重时机 :
- 固定值去重在
i
循环开始时 - 双指针去重在找到解后立即执行
- 固定值去重在
- 指针移动 :
- 找到解后需同时移动双指针(不能只移一边)
总结与思考
- 排序是基础:有序数组才能使用双指针技巧
- 去重是关键:三重去重(固定值 + 左指针 + 右指针)缺一不可
- 双指针的威力:将 O(n³) 暴力解优化到 O(n²)
- 适用场景:多数 N 数之和问题可转化为双指针思路(如两数之和、四数之和)
学习建议 :理解去重逻辑后,尝试解决 四数之和 巩固此方法!