前言
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
输入:nums = []
输出:[]
输入:nums = [0]
输出:[]
一、解题思路
根据题目描述,最简单的方式是使用暴力循环的算法,对于三个元素,每个都将数组从头到尾循环一边,将得到的三个元素相加进行判断。但是这种做法使时间复杂度为
O
(
N
3
)
O(N^3)
O(N3).在Leetcode上提交也会显示超出时间限制。为了简化时间复杂度可以使用双指针的方式。首先将数组按照升序排列,对于第一个元素,我们选择遍历的数组的方式来寻找。对于第二个和第三个元素,设置左右指针分别指向数组的左右端点,然后分两种情况进行讨论。
第一种情况,将左指针向右移动:
nums[first]+nums[second]+nums[third]<0
第二种情况,将右指针向左移动:
nums[first]+nums[second]+nums[third]>0
因为数组是按照升序进行排列的,所以不会出现遗漏的情况
二、JAVA 代码
List<List<Integer>> result=new ArrayList<List<Integer>>();
if (nums.length<=2||nums==null) return result;
Arrays.sort(nums);
for (int first=0;first<nums.length;first++){
if (first>0&&nums[first]==nums[first-1]) continue;
int second=first+1,target=-nums[first];
int third=nums.length-1;
while (second<third){
if (nums[second]+nums[third]>target){
while (third>second&&nums[third-1]==nums[third])
third--;
third--;
}
else if (nums[second]+nums[third]<target){
while (second<third&&nums[second+1]==nums[second])
second++;
second++;
}
else{
List<Integer> temp=new ArrayList<>();
temp.add(nums[first]);
temp.add(nums[second]);
temp.add(nums[third]);
result.add(temp);
while (second<third&&nums[third-1]==nums[third])
third--;
third--;
}
}
}
return result;
总结
这道题除了巩固双指针的用法,还需要注意,对数组元素查找的前一步是对数组进行排序,这样可以提高查找效率。此外,对数组进行遍历也要考虑越界情况,可以在循环中设置if判断语句当下标>1或者<右端点是进行运算。最后,在左右指针的移动算法中,每一次移动都需要考虑左指针是否小于右指针,例如最内层的三个while循环,将second<right去掉的话,一些特殊情况就会报错,例如[0,0,0,0]