赞
踩
描述:
给你一个整数数组 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
-105 <= nums[i] <= 105
思路:
输出的顺序和三元组的顺序并不重要,上来先排序,考虑枚举nunms[ i ],三数之和为0,即
-nums[ i ] = nums[ j ] + nums[ k ] ;类似167题两数之和.题目要求不重复,加一个判断就好
题解:
- class Solution {
- public List<List<Integer>> threeSum(int[] nums) {
- Arrays.sort(nums);
- int len = nums.length;
- List<List<Integer>> ans = new ArrayList();
- if(len<3)
- return ans;
- for(int i=0; i<len-2; i++){
- if(nums[i] > 0)
- break;
- //小优化,若nums[i]与后面两个相对最小的数相加大于0,nums[i]后面的数更不符合条件
- if(nums[i] + nums[i+1] + nums[i+2] > 0)
- break;
- // 若nums[i]与后面最大的两个数相加都小于0,跳过nums[i]
- if(nums[i] + nums[len-1] + nums[len-2] < 0)
- continue;
- if(i>0 && nums[i] == nums[i-1])
- continue;
- int L = i+1;
- int R= len-1;
- while(L<R){
- int sum = nums[i] +nums[L] +nums[R];
- if(sum==0){
- ans.add(Arrays.asList(nums[i], nums[L], nums[R]));
- while(L<R && nums[L] == nums[L+1])
- L++;
- while(L<R && nums[R] == nums[R-1])
- R--;
- L++;
- R--;
- }
- else if(sum<0)
- L++;
- else
- R--;
- }
- }
- return ans;
- }
- }
复杂度分析:
时间复杂度:O(N^2),其中 N 是数组 nums 的长度。枚举for循环O(N), 里面双指针O(N),所以O(N^2)
空间复杂度:O(logN)。力扣认为忽略存储答案的空间,额外的排序的空间复杂度为 O(logN)。然而我们修改了输入的数组 nums,在实际情况下不一定允许,因此也可以看成使用了一个额外的数组存储了 nums 的副本并进行排序,空间复杂度为 O(N)。
作者:力扣官方题解
原题链接:15. 三数之和
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。