这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战
这个系列没啥花头,就是纯 leetcode 题目拆解分析,不求用骚气的一行或者小众取巧解法,而是用清晰的代码和足够简单的思路帮你理清题意。让你在面试中再也不怕算法笔试。
160. 搜索二维矩阵II (search-a-2d-matrix-ii)
标签
- 中等
题目
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:
每行的元素从左到右升序排列。 每列的元素从上到下升序排列。
示例 1
输入: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
输入: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)
标签
- 中等
- 数学
题目
给定正整数 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
,我看到就通过,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧