leetcode 第18题四数之和

200 阅读1分钟

题目: 给你一个由 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 你可以按 任意顺序 返回答案 。[题目链接](leetcode.cn/problems/4s…

我的JavaScript解法:

var fourSum = function(nums, target) {
  const result = []
  const length = nums.length
  if (nums == null || length < 4)
    return result
  nums.sort((a, b) => a -b) // 排序
  for (let i = 0; i < length-3; i++) {
    if (i>0 && nums[i] == nums[i-1]) continue;
    let threeTarget = target - nums[i]
    let threeResult = threeSum(nums, i+1, threeTarget)
    threeResult.length && threeResult.forEach(item => {
      item.unshift(nums[i])
      result.push(item)
    })
  }
  return result;
};


var threeSum = function(nums, startIndex, target) {
  const result = []
  const length = nums.length
  if (nums == null || (length - startIndex) < 3) return result
  for (let i = startIndex; i < length -2; i++) {
    if (i>startIndex && nums[i] == nums[i-1]) continue;
    let left = i +1, right = length -1;
    while(left < right) {
      const sum = nums[i] + nums[left] + nums[right]
      if (sum === target) {
        result.push([nums[i], nums[left], nums[right]])
        while(nums[left] == nums[left+1]) left++; // 第二个数去重
        while(nums[right] == nums[right-1]) right--; // 第三个数去重
        left++;
        right--;
      } else if(sum < target) {
        left++
      } else if (sum > target){
        right--
      }
    }
  }
  return result;
}

解析: 双指针+排序

  • 时间复杂度:for调用threeSumO(n2)O(n^2) = O(n3)O(n^3)
  • 空间复杂度: O(1)O(1)

拓展nSum问题

const nSum = function(nums, n, start, target) {
  const result = [];
  const length = nums.length;
  if (n < 2 || length < n) return result;
  if (n == 2) {
    let left = start, right = length - 1;
    while (left < right) {
      const sum = nums[left] + nums[right]
      if(sum < target) {
        while(left < right && nums[left] == nums[left+1]) left++;
      } else if ( sum > target) {
        while(left < right && nums[right] == nums[right-1]) right--;
      } else {
        result.push([nums[left], nums[right]]);
        while(left < right && nums[left] == nums[left+1]) left++;
        while(left < right && nums[right] == nums[right-1]) right--;
      }
    }
  } else {
    for (let i = start; i < length; i++) {
      const subResult = nSum(nums, n-1, i + 1, target - nums[i]);
      subResult.length && subResult.forEach(item => {
        item.unshift(nums[i])
        result.push(item)
      })
      while(i < length-1 && nums[i] == nums[i+1]) i++;
    }
  }
  console.log(n, result)
  return result;
}