题目描述
给你一个整数数组
nums
,判断是否存在三元组[nums[i], nums[j], nums[k]]
满足i != j
、i != k
且j != k
,同时还满足nums[i] + nums[j] + nums[k] == 0
。请你返回所有和为0
且不重复的三元组。注意:答案中不可以包含重复的三元组。
示例 1:输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]] 解释: nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。 nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。 nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。 不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。 注意,输出的顺序和三元组的顺序并不重要。
示例 2:输入:nums = [0,1,1] 输出:[] 解释:唯一可能的三元组和不为 0 。
示例 3:输入:nums = [0,0,0] 输出:[[0,0,0]] 解释:唯一可能的三元组和为 0 。
提示:
3 <= nums.length <= 3000
-
<= nums[i] <=
解题思路
要在数组中找出所有和为 0 且不重复的三元组,可以采用排序+双指针的方法。具体步骤如下:
- 排序:首先对数组进行排序,这样可以方便地使用双指针来寻找三元组,并且可以避免重复。
- 遍历数组:从第一个元素开始,固定一个元素,接着使用双指针的方法寻找其后面的元素组成的三元组。
- 双指针查找:对于固定的元素
nums[i]
,使用左指针left
指向i+1
,右指针right
指向数组的末尾。当nums[i] + nums[left] + nums[right] == 0
时,说明找到了一个三元组,将其加入结果集。然后为了避免重复,需要跳过重复的元素。 - 移动指针:如果三者之和大于 0,说明右指针指向的元素过大,需要将右指针左移;如果三者之和小于 0,说明左指针指向的元素过小,需要将左指针右移。
- 跳过重复元素:为了避免重复的三元组,对于
nums[i]
,nums[left]
和nums[right]
都需要跳过重复的元素。
复杂度分析
-
时间复杂度:O(n^2)。排序的时间复杂度为 O(n log n)。双指针查找所有三元组的时间复杂度为 O(n^2),因为对于每个元素,内层循环遍历一次其后的元素。
-
空间复杂度:O(1)。只使用了常数级别的额外空间(不包括存储结果所用的空间),因此空间复杂度为 O(1)。
代码实现
package org.zyf.javabasic.letcode.hot100.twopoint;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @program: zyfboot-javabasic
* @description: 三数之和
* @author: zhangyanfeng
* @create: 2024-08-21 20:59
**/
public class ThreeSumSolution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums); // 排序数组
for (int i = 0; i < nums.length - 2; i++) {
// 跳过重复的元素
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
int left = i + 1;
int right = nums.length - 1;
while (left < right) {
int sum = nums[i] + nums[left] + nums[right];
if (sum == 0) {
result.add(Arrays.asList(nums[i], nums[left], nums[right]));
// 跳过重复的 left 元素
while (left < right && nums[left] == nums[left + 1]) {
left++;
}
// 跳过重复的 right 元素
while (left < right && nums[right] == nums[right - 1]) {
right--;
}
left++;
right--;
} else if (sum < 0) {
left++;
} else {
right--;
}
}
}
return result;
}
public static void main(String[] args) {
ThreeSumSolution solution = new ThreeSumSolution();
int[] nums1 = {-1,0,1,2,-1,-4};
System.out.println(solution.threeSum(nums1)); // 输出: [[-1,-1,2],[-1,0,1]]
int[] nums2 = {0,1,1};
System.out.println(solution.threeSum(nums2)); // 输出: []
int[] nums3 = {0,0,0};
System.out.println(solution.threeSum(nums3)); // 输出: [[0,0,0]]
}
}
具体可参考:https://zyfcodes.blog.csdn.net/article/details/141401712