探索算法乐园:挑战四数之和,解密数字交织的谜题

148 阅读3分钟

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

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

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

解题思路: 四数之和问题可以看做是三数之和问题的扩展,可以采用类似的思路来解决。

首先对数组进行排序,然后枚举前两个数(i 和 j),再使用双指针法找到剩下的两个数(left 和 right),使它们的和为 target。具体步骤如下:

  1. 对数组 nums 进行排序,方便后续的操作。

  2. 枚举第一个数 i,遍历范围为 [0, nums.length-3],如果 i>0 且 nums[i] === nums[i-1],则跳过本次循环,避免重复。

  3. 枚举第二个数 j,遍历范围为 [i+1, nums.length-2],如果 j>i+1 且 nums[j] === nums[j-1],则跳过本次循环,避免重复。

  4. 定义双指针 left 和 right,分别指向 j+1 和 nums.length-1,当 left<right 时循环:

  • 计算四个数的和 sum = nums[i] + nums[j] + nums[left] + nums[right],如果 sum 等于 target,则将这四个数加入到结果数组 res 中,并移动 left 和 right 指针,同时跳过重复的元素。
  • 如果 sum 小于 target,则将 left 指针向右移动一位。
  • 如果 sum 大于 target,则将 right 指针向左移动一位。
  1. 返回结果数组 res。

这样的时间复杂度为 O(n^3),空间复杂度为 O(1)。 运行代码:

function fourSum(nums, target) {
    let res = [];
    if (nums.length < 4) return res;
    nums.sort((a, b) => a - b); // 排序
    for (let i = 0; i < nums.length - 3; i++) {
      if (i > 0 && nums[i] === nums[i - 1]) continue; // 避免重复
      for (let j = i + 1; j < nums.length - 2; j++) {
        if (j > i + 1 && nums[j] === nums[j - 1]) continue; // 避免重复
        let left = j + 1, right = nums.length - 1;
        while (left < right) {
          let sum = nums[i] + nums[j] + nums[left] + nums[right];
          if (sum === target) {
            res.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 res;
}

当运行上述 JavaScript 代码时,可以按照以下步骤进行思考:

  1. 输入待求解的数组 nums 和目标值 target。
  2. 调用 fourSum 函数,传入数组 nums 和目标值 target。
  3. 在函数内部,首先对输入的数组 nums 进行排序,以便后续的操作。
  4. 然后使用两层嵌套循环来枚举第一个数和第二个数(i 和 j),并在内部使用双指针法找到剩下的两个数(left 和 right),使它们的和为 target。
  5. 当找到满足条件的四个数时,将其加入结果数组 res 中。
  6. 最终返回结果数组 res,即为符合条件的四个数的组合。

在实际运行时,可以针对不同的输入数据进行测试,观察程序的输出结果,以验证代码的正确性。