打卡-算法训练营-Day7 | 383. 赎金信;454.四数相加II ;15. 三数之和 ;18. 四数之和

80 阅读3分钟

赎金信

leetcode链接:leetcode.cn/problems/ra…

是242.有效的字母异位词的拓展题

两道题目思路的区别:

242中,两个字符串所包含的字母和出现的次数肯定是相同的,先将字符串1的字母次数映射到哈希表,再将字符串2的字母次数从哈希表中删除,如果两个是有效的字母异位词,最终的哈希表肯定全部都是0

383中,两个字符串所包含的字母和出现次数是会不相同的,如果按照242的思路,哈希表里面会存在不是0的元素,需要判这个元素是否已经在哈希表中,存在的话再删除,不存在则不做处理

var canConstruct = function(ransomNote, magazine) {
  let hashMap = new Array(26).fill(0);
  let offset = "a".charCodeAt(0);

  for (let i = 0; i < ransomNote.length; i++) {
    hashMap[ransomNote.charAt(i).charCodeAt(0) - offset]++;
  }

  for (let i = 0; i < magazine.length; i++) {
    // 如果在哈希表中出现过才做减法,注意与242题目的区别
    let target = magazine.charAt(i).charCodeAt(0) - offset;
    if (hashMap[target]) {
      hashMap[target]--;
    }
  }

  for (let i = 0; i < hashMap.length; i++) {
    if (hashMap[i] !== 0) {
      return false;
    }
  }
  return true;
};

四数相加II

leetcode链接:leetcode.cn/problems/4s…

看了视频讲解后才做出来(想着用map解决,但是变量太多了,map只存两个变量,不知道怎么用)

四数相加:a+b+c+d=0 -> a+b=-(c+d)

变量太多了就相加后再存起来(最小单位去处理)

四个数组A,B,C,D,A+B的和sum1存储在哈希表中,C+D的和sum2存储在哈希表中,判断sum1是否等于-sum2,实际代码可以优化,只使用一个map

还需要理解为什么是count += map[target],而不是count++

var fourSumCount = function(nums1, nums2, nums3, nums4) {
  let count = 0;
  let map = {};

  // 处理A,B数组
  for (let i = 0; i < nums1.length; i++) {
    for (let j = 0; j < nums2.length; j++) {
      let sum1 = nums1[i] + nums2[j];
      if (map[sum1]) {
        map[sum1]++;
      } else {
        map[sum1] = 1;
      }
    }
  }

  // 处理C,D数组
  for (let i = 0; i < nums3.length; i++) {
    for (let j = 0; j < nums4.length; j++) {
      let target = 0 - (nums3[i] + nums4[j]);
      if (map[target]) {
        // 为什么不是count++?
        count += map[target];
      }
    }
  }
  return count;
};

三数之和

leetcode链接:leetcode.cn/problems/3s…

不需要返回数组下标,可以排序,固定循环i,剩下的用双指针根据sum与target的大小进行左右收缩,题目难点在于去重

var threeSum = function(nums) {
  // 先对数组进行排序,方便去重
  nums.sort((a, b) => a - b);

  let result = [];

  for (let i = 0; i < nums.length - 2; i++) {
    // i去重
    if (i !== 0) {
      if (nums[i] === nums[i - 1]) {
        continue;
      }
    }
    let left = i + 1;
    let right = nums.length - 1;
    while (left < right) {
      // left去重
      if (left > i + 1 && nums[left] === nums[left - 1]) {
        left++;
        continue;
      }

      // right去重
      if (right < nums.length - 1 && nums[right] === nums[right + 1]) {
        right--;
        continue;
      }

      let sum = nums[i] + nums[left] + nums[right];
      if (sum === 0) {
        result.push([nums[i], nums[left], nums[right]]);
        left++;
        right--;
      } else if (sum < 0) {
        left++;
      } else {
        right--;
      }
    }
  }
  return result;
};

四数之和

leetcode链接:leetcode.cn/problems/4s…

在三数之和的思路上,多加一层循环处理,难点也是在去重

var fourSum = function(nums, target) {
    nums.sort((a, b) => a - b);

    let result = [];

    for (let i = 0; i < nums.length - 3; i++) {
        // i去重
        if (i !== 0 && nums[i] === nums[i-1]) {
            continue;
        }
        for (let j = i + 1; j < nums.length - 2; j++) {
            // j去重
            if (j > i + 1 && nums[j] === nums[j-1]) {
                continue;
            }
            let left = j + 1;
            let right = nums.length - 1;
            while (left < right) {
                // left去重
                if (left > j + 1 && nums[left] === nums[left-1]) {
                    left++;
                    continue;
                }
                // right去重
                if (right < nums.length - 1 && nums[right] === nums[right+1]) {
                    right--;
                    continue;
                }
                let sum = nums[i] + nums[j] + nums[left] + nums[right];
                if (sum === target) {
                    result.push([nums[i], nums[j], nums[left], nums[right]]);
                    left++;
                    right--;
                } else if (sum < target) {
                    left++;
                } else {
                    right--;
                }
            }
        }
    }
    return result;
};