LeetCode之三数之和
题目描述
给定一个包含 n 个整数的数组 nums,判断 nums
中是否存在三个元素 a,b,c ,使得 a + b + c = 0
找出所有满足条件且不重复的三元组。
简而言之,就是从给定的数组中找到所有三个数之和为0的数,并且还
不能有重复,根据题意,首先想到的是暴力解法,使用三层循环,这样
时间复杂度太高,并不适用,这里采用双指针方法
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
class Solution {
public List<List<Integer>> threeSum(int[] a) {
List<List<Integer>> list = new ArrayList<>();
int n;
// 首先进行边界值判断,传入数组不能为空
if (a == null || (n = a.length) == 0)
return list;
// 数组中数据先进行排序,这样便于使用双指针,双向遍历
// 假若先前顺序为 [-1, 0, 1, 2, -1, -4]
// 排序后就成为 [-4,-1,-1,0,1,2]
Arrays.sort(a);
for (int i = 0; i < n; i++) {
// 这里表示第一个元素值大于0 直接退出
// 若最前面的元素值大于0,三个数之和永远大于0
if (a[i] > 0) break;
// 元素值有重复,直接跳过
if (i > 0 && a[i] == a[i - 1]) continue;
// 注意这里是双指针
// 左指针指向最开始元素的后一个元素
// 右指针指向最后一个元素
int j = i + 1, k = n - 1;
while (j < k) {
int sum = a[j] + a[k] + a[i];
if (sum == 0) {
// 若三个数之和为0,加入
List<Integer> l = new ArrayList<>(3);
l.add(a[i]);
l.add(a[j]);
l.add(a[k]);
list.add(l);
//这两部都是避免数据重复,排重的功能
while(j < k && a[j] == a[j + 1]) j++;
while(j < k && a[k] == a[k - 1]) k--;
//左右指针向中间靠拢
j++;k--;
} else if (sum > 0) {
k--; //表明三数之和大于0,就要将右指针向左移动
} else {
j++; //表明三数之和小于0,就要将左指针向右移动
}
}
}
return list;
}
}