LeetCode 热题 100 之第6题 三数之和(JavaScript篇)leetcode三数之和为0
LeetCode 热题 100 之第6题 三数之和(JavaScript篇)要求找到数组中所有不重复的三元组,使得它们的和为零,可以使用双指针法来解决这个问题,首先排序数组,然后遍历每个元素,并使用双指针在剩余部分查找另外两个数,使得它们的和与当前元素相加为零,这种方法的时间复杂度为 O(n^2),适用于大部分情况,在 JavaScript 中,可以使用Array.prototype.sort()
对数组进行排序,并使用for
循环和while
循环实现双指针的查找。
LeetCode 热题 100 之第6题 三数之和(JavaScript篇) 描述
LeetCode 热题 100 之第6题,题目名称为“三数之和”,题目要求我们在一个数组中找到所有不重复的三元组,使得这三个数的和为零,每个三元组中的元素按升序排列,给定数组 nums = [-1, 0, 1, 2, -1, -4]
,则所有满足条件的三元组为 [-1, -1, 2]
、[-1, 0, 1]
。
解题思路
解决这个问题的关键在于如何有效地减少搜索空间,避免重复解,一种常见的方法是使用双指针法结合排序,具体步骤如下:
- 排序:首先对数组进行排序,这是解决问题的前提,排序后,相同的元素会相邻,便于后续处理重复元素。
- 遍历:使用三个指针进行遍历,第一个指针从数组的第一个元素开始,第二个和第三个指针分别从第二个和倒数第三个元素开始,向中间靠拢。
- 移动指针:通过移动指针来缩小搜索范围,如果三个数的和等于零,则找到了一个解;如果和小于零,则左移第一个指针以增加总和;如果和大于零,则右移第三个指针以减小总和。
- 跳过重复元素:在遍历过程中,如果发现当前元素与之前元素相同,则跳过以避免重复解。
代码实现(JavaScript)
下面是使用 JavaScript 实现该算法的代码:
/** * @param {number[]} nums * @return {number[][]} */ var threeSum = function(nums) { const result = []; nums.sort((a, b) => a - b); // 对数组进行排序 for (let i = 0; i < nums.length - 2; i++) { // 跳过重复元素,避免重复解 if (i > 0 && nums[i] === nums[i - 1]) continue; let left = i + 1; // 左指针 let right = nums.length - 1; // 右指针 while (left < right) { const sum = nums[i] + nums[left] + nums[right]; if (sum === 0) { result.push([nums[i], nums[left], nums[right]]); // 跳过重复元素,避免重复解 while (left < right && nums[left] === nums[left + 1]) left++; while (left < right && nums[right] === nums[right - 1]) right--; left++; right--; } else if (sum < 0) { left++; // 和小于零,左移左指针以增加总和 } else { right--; // 和大于零,右移右指针以减小总和 } } } return result; };
代码解析
- 排序:
nums.sort((a, b) => a - b);
对数组进行升序排序,这是解决问题的前提,因为排序后相同的元素会相邻,便于后续处理重复元素。 - 遍历:
for (let i = 0; i < nums.length - 2; i++)
使用第一个指针i
从数组的第一个元素开始遍历。left
和right
分别指向i
的下一个位置和数组的最后一个位置,通过移动这三个指针来缩小搜索范围。 - 移动指针:根据当前三个数的和
sum
调整指针的位置。sum
为零,则找到了一个解;sum
小于零,则左移左指针left
以增加总和;sum
大于零,则右移右指针right
以减小总和。 - 跳过重复元素:在遍历过程中,如果发现当前元素与之前元素相同,则跳过以避免重复解,具体实现为:
if (i > 0 && nums[i] === nums[i - 1]) continue;
以及在找到解后继续跳过重复元素:while (left < right && nums[left] === nums[left + 1]) left++;
和while (left < right && nums[right] === nums[right - 1]) right--;
。
时间复杂度分析
该算法的时间复杂度为 O(n^2),n 是数组的长度,这是因为我们使用了三个指针进行遍历和移动,每个指针最多遍历 n 个元素,由于我们跳过了重复元素,实际运行时间会比 O(n^3) 更优,空间复杂度为 O(1),除了返回结果外没有使用额外的空间。