LeetCode三数之和
题目
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:
输入:nums = []
输出:[]
实现思想:
暴力:
直接遍历所有组合,选出其中的符合要求的组合,再利用哈希进行去重处理。时间复杂度较大为O(N^3)
排序 + 双指针:
这种方法可以更简单高效地去掉重复解。
因为先排序好后,可以直接忽略掉连续3个正数或负数的情况,提高速度。排序好后,用双指针标记记录位置,可以避免重复解的出现。
原理:
令左指针指向当前元素的下一位(下标i+1),右指针指向末位(下标length-1),求和,和大于0时,右指针左移(令和变小),和小于0时,左指针右移(令和变大),直到两指针相碰或者和为0。和为0时,进行判断左右指针的下一位是否相同,相同则跳过(避免重复解)。
实现代码:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> lists = new ArrayList<>();
//排序
Arrays.sort(nums);
//双指针
int len = nums.length;
for(int i = 0;i < len;++i) {
if(nums[i] > 0) return lists;
if(i > 0 && nums[i] == nums[i-1]) continue;
int curr = nums[i];
int L = i+1, R = len-1;
while (L < R) {
int tmp = curr + nums[L] + nums[R];
if(tmp == 0) {
List<Integer> list = new ArrayList<>();
list.add(curr);
list.add(nums[L]);
list.add(nums[R]);
lists.add(list);
while(L < R && nums[L+1] == nums[L]) ++L;
while (L < R && nums[R-1] == nums[R]) --R;
++L;
--R;
} else if(tmp < 0) {
++L;
} else {
--R;
}
}
}
return lists;
}
时间复杂度:
O(n^2)