Leetcode 每日一题 15.三数之和
引言
在算法的世界里,有些问题虽然看似简单,但却是锻炼算法思维的绝佳练习。今天,我们将深入探讨一个在面试中经常出现的问题——“三数之和”问题。这个问题不仅考验我们对数组操作的熟练程度,还考察我们如何利用数组的特性来优化算法。本文将详细介绍如何使用排序和双指针法解决“三数之和”问题,并提供Java语言的实现。
问题背景
给定一个整数数组 nums
,我们的任务是找出所有和为 0 且不重复的三元组。这意味着我们需要找出数组中的三个不同索引 i
、j
、k
,使得 nums[i] + nums[j] + nums[k] = 0
。这个问题实际上是在询问,如何通过选择三个元素来使它们的和为零。
输入输出规范
输入: 整数数组 nums
,一个包含整数的数组。
输出: 整数三元组的列表 result
,表示所有和为 0 且不重复的三元组。
示例解析
示例 1: 输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释: nums[0] + nums[1] + nums[4] = (-1) + 0 + 1 = 0
。 nums[0] + nums[3] + nums[5] = (-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。
算法策略
排序和双指针法是解决此类问题的常用策略。我们首先对数组进行排序,然后使用两个指针分别从排序后的数组的两端开始,通过调整这两个指针的位置来寻找能够构成和为0的三个数。
Java代码实现
java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums); // 对数组进行排序
List<List<Integer>> result = new ArrayList<>();
for (int i = 0; i < nums.length - 2; i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue; // 跳过重复的元素
int left = i + 1;
int right = nums.length - 1;
while (left < right) {
int sum = nums[i] + nums[left] + nums[right];
if (sum < 0) {
left++; // 需要更大的数
} else if (sum > 0) {
right--; // 需要更小的数
} else {
result.add(Arrays.asList(nums[i], nums[left], nums[right])); // 找到和为0的三元组
while (left < right && nums[left] == nums[left + 1]) left++; // 跳过重复的元素
while (left < right && nums[right] == nums[right - 1]) right--; // 跳过重复的元素
left++;
right--;
}
}
}
return result; // 返回所有和为0的三元组
}
}
复杂度分析
时间复杂度: O(n^2),其中 n 是数组 nums
的长度。排序的时间复杂度为 O(nlogn),双指针法的时间复杂度为 O(n^2)。
空间复杂度: O(1),只需要常量级的额外空间来存储结果。
通过图片
LeetCode地址
15. 三数之和 - 力扣(LeetCode)
结语
通过排序和双指针法,我们不仅解决了“三数之和”问题,还展示了如何利用数组的特性来优化算法。这种方法的时间复杂度和空间复杂度都非常低,适用于处理大规模数据集。希望这篇文章能够帮助你深入理解排序和双指针法,并将其应用到实际问题中。如果你有任何疑问或想要进一步探讨,欢迎在评论区交流。同时,如果你觉得这篇文章对你有帮助,不妨点个赞或者分享给需要的朋友。让我们一起进步,一起成长!