【leetCode】每日一题 四数之和

1,084 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情

18. 四数之和

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

0 <= a, b, c, d < n a、b、c 和 d 互不相同 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
-109 <= nums[i] <= 109
-109 <= target <= 109

解题思路

先给数组从小到大排序,然后双指针lo和hi分别在数组开头和结尾,这样就可以控制nums[lo]和nums[hi]这两数之和的大小
如果你想让它俩的和大一些,就让lo++,如果你想让它俩的和小一些,就让hi--。
基于两数之和可以得到一个万能函数nSumTarget,具体思路可见题解一个函数秒杀 2Sum 3Sum 4Sum 问题'

代码实现

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[][]}
 */
var fourSum = function (nums, target) {
  // 先排序
  nums.sort((a, b) => a - b);
  /*
  注意:调用这个函数之前一定要先给 nums 排序
  n 填写想求的是几数之和,start 从哪个索引开始计算(一般填 0),target 填想凑出的目标和
   */
  const nSumTarget = (nums, n, start, target) => {
    let size = nums.length;
    let res = [];
    // 至少是 2Sum,且数组大小不应该小于 n
    if (n < 2 || size < n) return res;
    // 2Sum 是 base case
    if (n == 2) {
      // 双指针那一套操作
      let lo = start,
        hi = size - 1;
      while (lo < hi) {
        let sum = nums[lo] + nums[hi];
        let left = nums[lo],
          right = nums[hi];
        if (sum < target) {
          while (lo < hi && nums[lo] == left) lo++;
        } else if (sum > target) {
          while (lo < hi && nums[hi] == right) hi--;
        } else {
          res.push([left, right]);
          while (lo < hi && nums[lo] == left) lo++;
          while (lo < hi && nums[hi] == right) hi--;
        }
      }
    } else {
      // n > 2 时,递归计算 (n-1)Sum 的结果
      for (let i = start; i < size; i++) {
        let sub = nSumTarget(nums, n - 1, i + 1, target - nums[i]);
        for (let arr of sub) {
          arr.push(nums[i]);
          res.push(arr);
        }
        while (i < size - 1 && nums[i] == nums[i + 1]) i++;
      }
    }
    return res;
  };
  // n 为 4,从 nums[0] 开始计算和为 target 的四元组
  return nSumTarget(nums, 4, 0, target);
};

如果你对这道题目还有疑问的话,可以在评论区进行留言;

\