LeetCode.M15
题目:
题目大意:
如图所示。
数据范围:
如图所示
思路:
排序+双指针。首先明确题目要求答案不允许重复。如何保证这一点呢?假设我们有一个数组nums:a1 a2 a3 b1 b2 b3 c1c2 c3 d1 d2 d3 ,其中a + b + c = 0。
- 第一重循环枚举first时,首先first = a1,又知后面存在b、c使得 a + b + c = 0,则(a1,b,c)为一个答案,但是第一个a后面还有两个a,这两个a都会和后面的b、c组成一个答案,造成了重复,所以,在枚举first时,我们要求这次的first和上一次循环的firt不同,所以在处理完第一个a时,跳过其后面两个a,直接开始处理第一个不等于它前面元素的值b,此时first = b。这样就保证了firts不重复。
- 第二重循环枚举second,与枚举first同理,处理的是first后的第一个元素,或者是不等于它前一个元素值的元素,这样就保证了second不重复。由于third = -(first + second), 这样也保证了third不重复。
- 那么如何找到third呢?我们可以使用双指针,假设现在first = a1, 令target = -a1,second = a2, 在第二重循环中固定住second,则我们需要找到一个third满足 second + third = target, 初始时,令左指针l为a2的下标,右指针r为d3(可能的third值x)的下标,如果a2 + x > target,我们不断移动右指针,在l < r 的情况下,找到第一个使a2 + x <= target的 x。
- 如果 a2 + x == target 了,则说明找到了一个合法解,将(first(a1),second(a2), x)加入答案中。
- 如果 a2 + x < target,不需要向右移动r了,因为越向右移动x越小,此时我们应该去处理下一个second(b1,跳过了a3),这样才有可能使second + third = target。注意不需要将右指针重新赋为len - 1,因为下一个second(b1)的值肯定比此次second(a2)的值要大,为了满足second + third = target ,相应的third的值也会更小)。
- 如果右指针一直向左移动到l == r了,则说明找不到使a2 + x <= target的 x,该first找不到一个second和third,则继续遍历下一个first(b1)
代码:
import java.util.*;
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> lists = new ArrayList<>();
int len = nums.length;
Arrays.sort(nums);
for (int first = 0; first < len; first ++ ){
if (first > 0 && nums[first - 1] == nums[first])
continue;
int target = -nums[first], third = len - 1;
for (int second = first + 1; second < len; second ++ ){
if (second > first + 1 && nums[second - 1] == nums[second])
continue;
while (second < third && nums[third] + nums[second] > target){
third -- ;
}
if (second == third)
break;
if (nums[third] + nums[second] == target){
List<Integer> list = new ArrayList<>();
list.add(nums[first]);
list.add(nums[second]);
list.add(nums[third]);
lists.add(list);
}
}
}
return lists;
}
}
public class Main {
public static void main(String[] args) {
Solution solution = new Solution();
// int[] nums = new int[]{-1,0,1,2,-1,-4};
int[] nums = new int[]{-1, 0, 1, -1, 0, 1};
System.out.println(solution.threeSum(nums).toString());
}
}
时空复杂度分析等:
-
时间复杂度 : O(n^2)
-
空间复杂度 : 排序的空间复杂度