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

261 阅读2分钟

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

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

160. 搜索二维矩阵II (search-a-2d-matrix-ii)

标签

  • 中等

题目

leetcode 传送门

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:

每行的元素从左到右升序排列。 每列的元素从上到下升序排列。

示例 1

image.png

输入:matrix = [
[1,4,7,11,15],
[2,5,8,12,19],
[3,6,9,16,22],
[10,13,14,17,24],
[18,21,23,26,30]], target = 5
输出:true

示例 2

image.png

输入:matrix = [
[1,4,7,11,15],
[2,5,8,12,19],
[3,6,9,16,22],
[10,13,14,17,24],
[18,21,23,26,30]], target = 20
输出:false

基本思路

  • 思路其实很清晰了, 类似走格子
  • 我们可以从左下开始找, 也就是本例中的 18这个数
  • 比它大,往右走一步,比它小往上走一步直到找到答案

写法实现

const searchMatrix = function(matrix, target) {
  if (matrix.length === 0 || matrix[0]?.length === 0) {
    return false
  }
  // 边界值计算
  let rows = matrix.length, cols = matrix[0]?.length
  // 初始化左下角为起点, 最后一行的第一列
  let row = matrix.length - 1, col = 0
  // 不能超出边界
  while (row >= 0 && col < cols) {
    if (matrix[row][col] === target) {
      return true
    } else if (matrix[row][col] < target) {
      // 向右走
      col++
    } else {
      // 向上走
      row--
    }
  }
  // 超过边界
  return false
}

let matrix = [
[1,4,7,11,15],
[2,5,8,12,19],
[3,6,9,16,22],
[10,13,14,17,24],
[18,21,23,26,30]], target = 22

console.log(searchMatrix(matrix, target))

161. 完全平方数(perfect-squares)

标签

  • 中等
  • 数学

题目

leetcode 传送门

给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。

给你一个整数 n ,返回和为 n 的完全平方数的 最少数量 。

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。

示例 1

输入: n = 12
输出: 3 
解释: 12 = 4 + 4 + 4

示例 2

输入: n = 13
输出: 2
解释: 13 = 4 + 9

基本思路

还是我们的动态规划基本3步思路。

状态定义

我们的目标是求 以 n 数字为完全平方数的最少个数

那么就设 dp[i] 就是以 i 数字为和的完全平方数的最少个数, 那么 dp[n] 就是我们本题答案

状态转移

我们另起一个 j 从一开始,看 dp[i - j * j] 其实 就是 dp[i] 再加上 j 的平方,所以数量上就加 1, 方程就是

dp[i] = Math.min(dp[i], dp[i - j * j] + 1)

有人说不会出现这个情况吗,比如 12 算到 12 = 9 + 3 => dp[12] = dp[3] + 1

12 = 4 + 4 + 4 => dp[12] = dp[8] + 1 = dp[4] + 1 + 1 = 1 + 1 + 1

我们要注意 dp[4] = 1 , dp[3] = 3 所以我们算最小值时, j 变化之后还是能算出最小值的。

边界

dp[i] 最大的满足情况其实就是全拆成 1 相加i = 1 + 1 + 1+ ... + 1 (i 个 1)

写法实现

const numSquares = function (n) {
  let dp = new Array(n + 1).fill(0)
  for (let i = 1; i < n + 1; i++) {
    // 这是 i 最大的情况 i = 1 + 1 + 1+ ... i 个 1
    dp[i] = i
    for (let j = 1; i >= j * j; j++) {
      // 再跟 dp[i - j * j] + 1 最大的一个 当前 j 凑成下一个最小位
      dp[i] = Math.min(dp[i], dp[i - j * j] + 1)
    }
  }
  return dp[n]
}

let n = 12
console.log(numSquares(n))

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

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

参考