问题描述
给定一个整数数组 nums
,找出所有和为 0
且不重复的三元组 [nums[i], nums[j], nums[k]]
。
代码实现(Java)
class Solution { public List<List<Integer>> threeSum(int[] nums) { List<List<Integer>> result = new ArrayList<>(); Arrays.sort(nums); // 排序数组 for (int i = 0; i < nums.length; i++) { // 剪枝:若当前数大于0,直接返回结果 if (nums[i] > 0) { return result; } // 去重:跳过重复的第一个数 if (i > 0 && nums[i] == nums[i - 1]) { continue; } // 双指针法 int left = i + 1; int right = nums.length - 1; while (right > left) { int sum = nums[i] + nums[left] + nums[right]; if (sum > 0) { right--; // 和过大,右指针左移 } else if (sum < 0) { left++; // 和过小,左指针右移 } else { // 找到有效三元组 result.add(Arrays.asList(nums[i], nums[left], nums[right])); // 去重:跳过重复的左右元素 while (right > left && nums[right] == nums[right - 1]) right--; while (right > left && nums[left] == nums[left + 1]) left++; // 移动指针 right--; left++; } } } return result; } }
代码解析
-
排序数组
使用Arrays.sort(nums)
对数组排序,便于后续去重和双指针操作。 -
遍历固定第一个数
遍历数组,将每个元素作为三元组的第一个数。 -
剪枝优化
若当前数nums[i] > 0
,直接返回结果,因为后续数更大,无法组成和为0
的三元组。 -
去重第一个数
跳过与前一个数相同的元素,避免重复的三元组。 -
双指针法
-
左指针
left
从i + 1
开始,右指针right
从数组末尾开始。 -
计算三数之和
sum = nums[i] + nums[left] + nums[right]
。 -
根据
sum
调整指针:-
sum > 0
:右指针左移。 -
sum < 0
:左指针右移。 -
sum == 0
:记录结果,去重并移动指针。
-
-
-
去重左右指针
在找到有效三元组后,跳过所有重复的左右元素,避免重复解。
语法规则
-
泛型列表声明:
List<List<Integer>> result = new ArrayList<>();
-
数组排序:
Arrays.sort(nums);
-
快速创建列表:
Arrays.asList(a, b, c)
-
循环跳过重复元素:通过比较相邻元素并移动下标。
记忆方法
-
排序预处理:先排序,后续操作依赖有序性。
-
固定第一个数:遍历每个元素作为第一个数。
-
剪枝优化:第一个数若为正数,直接返回结果。
-
去重第一个数:跳过与前一个相同的元素。
-
双指针搜索:左指针从
i+1
开始,右指针从末尾开始。 -
调整指针逻辑:
-
和过大 → 右指针左移。
-
和过小 → 左指针右移。
-
和为0 → 记录结果,去重后移动指针。
-
-
去重左右指针:在找到解后,跳过所有重复的左右元素。
关键逻辑图示
排序 → 遍历i → 跳过重复i → 双指针 → 调整和 → 记录并去重
总结
这段代码通过排序、双指针和去重操作,高效地解决了三数之和问题。掌握其核心逻辑和语法规则后,可以轻松应对类似问题。