JavaScript算法每日一题四数之和

每日一题:每天一个新挑战;
循序渐进:从易到难,扎实掌握;
系统分类:按数据结构分类,有助于构建知识框架;
丰富题量:100 道精选题,覆盖简单/中等/困难难度。

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

  • 0 <= a, b, c, d < n
  • a、b、cd 互不相同
  • nums[a] + nums[b] + nums[c] + nums[d] == target

你可以按 任意顺序 返回答案 。

示例 1:

输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

示例 2:

输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]

提示:

  • 1 <= nums.length <= 200
  • -10^9 <= nums[i] <= 10^9
  • -10^9 <= target <= 10^9

代码卡片

JavaScript算法每日一题四数之和

题目解析

“四数之和”问题要求找到数组中四个不同元素的组合,使其和等于目标值,并且不能有重复的四元组。由于暴力解法的时间复杂度过高,因此我们需要使用更高效的方法来解决问题。

方法一:排序 + 双指针

  1. 排序:首先将数组进行排序,这样可以方便地跳过重复元素,并且简化后续步骤中的双指针操作。
  2. 四重循环:使用四重循环,其中外层两个循环固定两个数,内层两个循环使用双指针查找另外两个数,使得四个数的和等于目标值。
  3. 跳过重复:为了避免重复结果,我们在每次循环时都要检查当前数字是否和前一个数字相同,如果相同则跳过,以避免产生相同的四元组。
  • 时间复杂度: 排序的时间复杂度为 O(n log n),四重循环的时间复杂度为 O(n^3),所以总体的时间复杂度为 O(n^3)。
  • 空间复杂度: 由于只使用了常数级别的额外空间,空间复杂度为 O(1)。
var fourSum = function (nums, target) {
    nums.sort((a, b) => a - b);
    const result = [];
    const n = nums.length;

    for (let i = 0; i < n - 3; i++) {
        if (i > 0 && nums[i] === nums[i - 1]) continue; // 跳过重复元素
        for (let j = i + 1; j < n - 2; j++) {
            if (j > i + 1 && nums[j] === nums[j - 1]) continue; // 跳过重复元素
            let left = j + 1;
            let right = n - 1;
            while (left < right) {
                const sum = nums[i] + nums[j] + nums[left] + nums[right];
                if (sum === target) {
                    result.push([nums[i], nums[j], 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 < target) {
                    left++;
                } else {
                    right--;
                }
            }
        }
    }
    return result;
}

方法二:哈希表

使用哈希表存储数组中的元素及其下标,利用两数之和的思路,将问题转化为查找剩余两数之和等于 target – 当前两数之和 的问题。

var fourSum = function (nums, target) {
    nums.sort((a, b) => a - b);
    const result = [];
    const n = nums.length;

    for (let i = 0; i < n - 3; i++) {
        if (i > 0 && nums[i] === nums[i - 1]) continue;
        for (let j = i + 1; j < n - 2; j++) {
            if (j > i + 1 && nums[j] === nums[j - 1]) continue;
            const hashMap = new Map();
            for (let k = j + 1; k < n; k++) {
                const complement = target - nums[i] - nums[j] - nums[k];
                if (hashMap.has(complement)) {
                    result.push([nums[i], nums[j], complement, nums[k]]);
                    while (k + 1 < n && nums[k] === nums[k + 1]) k++;
                }
                hashMap.set(nums[k], k);
            }
        }
    }
    return result;
}

总结

  • 第一种方法通过排序和双指针可以有效避免重复组合,是较为常见的解法,适用于大部分情况。
  • 第二种方法通过哈希表加速查找,但可能在空间复杂度上表现略差。

最后

如果你有其他思路或方法,欢迎在评论区分享!祝你编码 ‍ 愉快!

发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/288982
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!

(0)
股市刺客的头像股市刺客
上一篇 4小时前
下一篇 3小时前

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注