三数之和
力扣题号15
题目描述:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 
 | 给你一个整数数组 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 。
 
 | 
这道题的解法最好是用双指针,为了效率更高首先需要将数组排序,然后遍历这个数组。i从下标0的地方开始,同时定义一个left为i+1的位置,定义right为数组结尾的位置。
在数组中找到a,bc,使得a+b+c= 0,在这里就相当于nums[i] + nums[left] + nums[right] = 0  接下来就该考虑双指针应该怎样移动
- 如果nums[i] + nums[left] + nums[right] > 0, 则说明此时三数之和大了,需要往小里移动,以为此时数组是有序的,所以只需要right指针向左移动,这样才能让三数之和小一点
- 如果nums[i] + nums[left] + nums[right] < 0, 则说明此时三数之和小了,left向右移动,才能使三数之和大一些,直到left与right相遇为止
 排序+双指针 
              
              | 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 
 | class Solution {public List<List<Integer>> threeSum(int[] nums) {
 Arrays.sort(nums);
 List<List<Integer>>result = new ArrayList<>();
 for (int i = 0; i < nums.length; i++) {
 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){
 if (nums[i] + nums[left] + nums[right] > 0){
 right--;
 }else if (nums[i] + nums[left] + nums[right] < 0){
 left++;
 }else {
 List<Integer> re = new ArrayList<>();
 re.add(nums[i]);
 re.add(nums[left]);
 re.add(nums[right]);
 result.add(re);
 while (right > left && nums[right] == nums[right-1]){
 right--;
 }
 while (right > left && nums[left] == nums[left + 1]){
 left++;
 }
 right--;
 left++;
 }
 }
 }
 return result;
 }
 }
 
 |