三数之和
力扣题号15
题目描述:
1 2 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相遇为止
排序+双指针
1 2 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; } }
|