算法|454.四数相加II 383. 赎金信 15. 三数之和 18. 四数之和

454.四数相加II

思路: a,b,c,d 四个数组,
1,循环把a,b 两个数组的值相加并存入map中,key为和, value为 出现的次数
2,循环c,d 2个数组,将结果 和map 中对比0-sum

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @param {number[]} nums3
 * @param {number[]} nums4
 * @return {number}
 */
var fourSumCount = function (nums1, nums2, nums3, nums4) {
    const map = new Map()
    for (n1 of nums1) {
        for (n2 of nums2) {
            let sum = n1 + n2
            map.set(sum, (map.get(sum) || 0) + 1)
        }
    }
    let count = 0
    for (s3 of nums3) {
        for (s4 of nums4) {
            let sum = s3 + s4
            count += map.get(0 - sum) || 0
        }
    }
    return count
};

383. 赎金信

思路:
巧妙利用map的减法操作,避免了两次对字符串进行hash求值,再比较的复杂计算

/**
 * @param {string} ransomNote
 * @param {string} magazine
 * @return {boolean}
 */
var canConstruct = function (ransomNote, magazine) {
    let map = {}
    for (let ch of magazine) {
        map[ch] = map[ch] ? map[ch] + 1 : 1
    }
    for (let ch of ransomNote) {
        if (map[ch] === undefined) return false
        map[ch] -= 1
        if (map[ch] < 0) return false
    }
    return true
};

15. 三数之和

思考: 双指针解法

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
// 思路: 双指针方法实现
var threeSum = function (nums) {
  // 排序
  nums.sort((a, b) => a - b);
  console.log(nums);
  let ans = [];
  // 循环遍历
  for (let i = 0; i < nums.length; i++) {
    let startNum = nums[i];
    let l = i + 1;
    let r = nums.length - 1;
    // 最小值大于0 边界 ans是全局变量, 不可以返回 return []
    if (startNum > 0) return ans;
    // 去重
    if (startNum === nums[i - 1]) continue;

    // 双指针解法
    while (l < r) {
      let lNum = nums[l];
      let rNum = nums[r];

      let total = startNum + lNum + rNum;
      if (total < 0) {
        l++;
      } else if (total > 0) {
        r--;
      } else {
        ans.push([startNum, lNum, rNum]);
        // 以下几行很难想的到
        while (l < r && nums[l] == nums[l + 1]) {
          l++;
        }
        while (l < r && nums[r] == nums[r - 1]) {
          r--;
        }
        l++;
        r--;
      }
    }
  }
  return ans;
};
console.log(threeSum([-1, 0, 1, 2, -1, -4]));

18. 四数之和

思考: 双指针解法, 比三数之和多一层for循环,也有点小变化

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[][]}
 */
var fourSum = function (nums, target) {
  const len = nums.length;
  if (len < 4) return [];
  nums.sort((a, b) => a - b);
  const res = [];
  //   起止点最大为len-3
  for (let i = 0; i < len - 3; i++) {
    // 去重i
    if (i > 0 && nums[i] === nums[i - 1]) continue;
    // 起始点最大为len-2
    for (let j = i + 1; j < len - 2; j++) {
      // 去重j
      if (j > i + 1 && nums[j] === nums[j - 1]) continue;
      let l = j + 1,
        r = len - 1;
      while (l < r) {
        const sum = nums[i] + nums[j] + nums[l] + nums[r];
        if (sum < target) {
          l++;
          continue;
        }
        if (sum > target) {
          r--;
          continue;
        }
        res.push([nums[i], nums[j], nums[l], nums[r]]);

        // 对nums[left]和nums[right]去重
        while (l < r && nums[l] === nums[++l]);
        while (l < r && nums[r] === nums[--r]);
      }
    }
  }
  return res;
};
// 三数之和  四数之和 和hash已经没有关系了, 是双指针解法

你可能感兴趣的:(算法)