一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情。
前言
笔者除了大学时期选修过《算法设计与分析》和《数据结构》还是浑浑噩噩度过的(当时觉得和编程没多大关系),其他时间对算法接触也比较少,但是随着开发时间变长对一些底层代码/处理机制有所接触越发觉得算法的重要性,所以决定开始系统的学习(主要是刷力扣上的题目)和整理,也希望还没开始学习的人尽早开始。
系列文章收录《算法》专栏中。
问题描述
给你一个包含 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 = []
输出:[]
示例 3:
输入:nums = [0]
输出:[]
提示:
- 0 <= nums.length <= 3000
- -10^5 <= nums[i] <= 10^5
剖析
这道题和两数之和有点像,只不过现在是三数之和,同时需要得到所有的符合的三元数组,同时不能重复。
所以我们可以对数组进行排序,如果发现和上一项相等的数字就直接跳过,然后利用双向指针进行移动,如果结果大于就把右指针往左移动,小于就继续遍历,等于就记录结果。
具体看代码。
代码
package com.study.algorithm.doublepointer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ThreeSum {
public static List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
int n = nums.length;
//排好序 方便跳过重复的元素
Arrays.sort(nums);
for (int first = 0; first < n; first++) {
//跳过重复的元素
if (first > 0 && nums[first] == nums[first - 1]) {
continue;
}
int thrid = n - 1;
int target = -nums[first];
for (int second = first + 1; second < n; second++) {
//跳过重复的元素
if (second > (first + 1) && nums[second] == nums[second - 1]) {
continue;
}
//大于的话就需要往左移动
while (thrid > second && nums[second] + nums[thrid] > target) {
thrid--;
}
//重合的话就退出循环
if (second == thrid) {
break;
}
if (nums[second] + nums[thrid] == target) {
List<Integer> resultChildren = new ArrayList<>();
resultChildren.add(nums[first]);
resultChildren.add(nums[second]);
resultChildren.add(nums[thrid]);
result.add(resultChildren);
}
}
}
return result;
}
public static void main(String[] args) {
System.out.println(threeSum(new int[]{-1, 0, 1, 2, -1, -4}));
}
}