前端算法必刷题系列[84]

356 阅读2分钟

这是我参与8月更文挑战的第9天,活动详情查看:8月更文挑战

这个系列没啥花头,就是纯 leetcode 题目拆解分析,不求用骚气的一行或者小众取巧解法,而是用清晰的代码和足够简单的思路帮你理清题意。让你在面试中再也不怕算法笔试。

前面连续的难题,来几个简单点放松下

154. 和为K的子数组(subarray-sum-equals-k)

标签

  • 中等
  • hash

题目

leetcode 传送门

给定一个整数数组一个整数 k,你需要找到该数组中和为 k连续的子数组的个数。

示例 1

输入:nums = [1,1,1], k = 2
输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。

基本思路

直接暴力枚举就行了,双重循环两个指针,i 和 j 计算 i, j首尾坐标的数组的和,等于 k 就 count++,非常简单暴力

暴力写法实现

function subarraySum(nums: number[], k: number): number {
  let sum = 0, count = 0
  for (let i = 0; i < nums.length; i++) {
    sum = 0
    for (let j = i; j < nums.length; j++) {
      sum += nums[j]
      if (sum === k) {
        count++;
      }
    }
  }
  return count
};

当然我们可以优化这个算法

我们就想到,这种问题一般优化就是做缓存,因为相邻顺序相加,其实很多加法是重复计算的, 我们枚举(i, j)就是 [j..i] 这个子数组和为 k 的情况

做缓存,那么我们 定义 pre[i][0..i]所有数的和

pre[i] = pre[i−1] + nums[i], 很明显的递推

那么 我们上面枚举的 [j..i] 这个子数组和为 k 这个条件我们可以转化为

[j..i] 这个子数组和我们可以表示为: preSum[i] - preSum[j−1]

那么就是 preSum[i] − preSum[j−1] === k 是我们想凑的等式,满足这个 count++

移项可得符合条件的下标 j 需要满足

preSum[j−1] === preSum[i] − k

接下来就是遍历 nums

  • 发现前缀和满足条件,count++
  • 保存前缀和与等式成立次数的映射
var subarraySum = function(nums, k) {
    let count = 0, preSum = 0;
    // 用 map 做缓存
    const map = new Map([[0, 1]]);

    for (let i = 0; i < nums.length; i++) {
        preSum += nums[i]
        // 发现前缀和满足条件,count++
        if (map.has(preSum - k)) {
            count += map.get(preSum - k);
        }
        // 保存前缀和与等式成立次数的映射
        if (map.has(preSum)) {
            map.set(preSum, map.get(preSum) + 1);
        } else {
            map.set(preSum, 1);
        }
    }
    return count;
};

let nums = [1, 1, 1, 2, 2, 3], k = 5
console.log(subarraySum(nums, k))

155. 找到所有数组中消失的数字(find-all-numbers-disappeared-in-an-array)

标签

  • 简单

题目

leetcode 传送门

给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有[1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。

示例 1

输入:nums = [4,3,2,7,8,2,3,1]
输出:[5,6]

示例 2

输入:nums = [1,1]
输出:[2]

基本思路

遇到这种从 1 - n的问题,就想想能不能用数组 index做点啥

另外去重,想到 Set

本题就可以用一个 set 来处理,找出缺失

  • 利用nums 长度来建立一个 len = n 的 set, 并把每个 index + 1作为set 的 value

  • 遍历 nums 把数组中存在的数从 set 中移出, 那么剩下的数就是缺失的

  • set 转数组输出

写法实现

let findDisappearedNumbers = (nums) => {
  let n = nums.length
  // 使用 set 来去重,并把 index + 1 作为输出,
  let set = new Set(new Array(n).fill(0).map((it, idx) => idx + 1))
  // 此时 Set { 1, 2, 3, 4, 5, 6, 7, 8 }
  for (let item of nums) {
    // 把数组中存在的数从 set 中移出, 那么剩下的数就是缺失的
    if (set.has(item)) {
      set.delete(item)
    }
  }
  return [...set]
}

console.log(findDisappearedNumbers([4,3,2,7,8,2,3,1]))

另外向大家着重推荐下这个系列的文章,非常深入浅出,对前端进阶的同学非常有作用,墙裂推荐!!!核心概念和算法拆解系列

今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦 点击此处交个朋友 Or 搜索我的微信号infinity_9368,可以聊天说地 加我暗号 "天王盖地虎" 下一句的英文,验证消息请发给我 presious tower shock the rever monster,我看到就通过,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧

参考