原题网址(中):https://leetcode-cn.com/problems/3sum/submissions/
原题网址(英):https://leetcode.com/problems/3sum/submissions/
题目:
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero
Note:The solution set must not contain duplicate triplets.
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4], 满足要求的三元组集合为:
[ [-1, 0, 1], [-1, -1, 2] ]
思路:
最开始想采用两数之和题中的创建哈希表的方法解决,但是太复杂,还容易出现hashmap中key相等的情况,需要处理冲突。后来更改为下面的方法。
-
排序
-
定义三个指针
a
,b
,c
-
a
指针固定时,b
与c
指针分别从数组的头与尾向中间移动。这里的数组是从nums[a+1]
开始的数组。每一次移动后,计算a
、b
、c
指针所在值和sum
。(1) 若
sum
为0,则此时a
、b
、c
为符合要求的三元组,b
指针与c
指针分别向后、向前移动一步,做下一个三元组搜索。
(2) 若sum
小于0,则说明在a
确定的情况下,如果存在符合条件的三元组,则三元组第二个数必定在b
指针后面,因此,b++
.
(3) 若sum
大于0,则说明在a
确定的情况下,如果存在符合条件的三元组,则三元组第三个数必定在c
指针前面,因此,c--
. -
a
指针从头遍历。每次遍历,重复步骤3.
注意:若移动时移动前后数组值相等,则继续移动。
时间复杂度:a
指针遍历需要
O
(
n
)
O(n)
O(n),每一次遍历b
指针与c
指针最多移动
n
n
n次,因此每一次遍历需要
O
(
n
)
O(n)
O(n),总的时间复杂度为
O
(
n
2
)
O(n^2)
O(n2).
代码:
public static List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
if (nums.length < 3)
return ans;
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
int j = i + 1;
int k = nums.length - 1;
while (j < k) {
int sum = nums[i] + nums[j] + nums[k];
if (sum == 0) {
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[k]);
ans.add(list);
j++;
k--;
while (j < k && nums[j] == nums[j - 1])
j++;
while (k > j && nums[k] == nums[k + 1])
k--;
} else if (sum < 0) {
j++;
} else {
k--;
}
}
while (i < nums.length - 1) {
if (nums[i] != nums[i + 1])
break;
else
i++;
}
}
return ans;
}