LeetCode刷题指南
第 0 章 hot100
0.1 哈希
0.2 双指针
0.3 滑动窗口
0.4 子串
0.5 普通数组
0.6 矩阵
0.7 链表
0.8 二叉树
0.9 图论
0.10 回溯
0.11 二分查找
0.12 栈
0.13 堆
0.14 贪心算法
0.15 动态规划
0.16 多维动态规划
0.17 技巧
第0-1章 面试经典150
0.1 数组/字符串
0.2 双指针
0.3 滑动窗口
链表
二叉树
第 1 章 最易懂的贪心算法
1.1 算法解释
1.2 分配问题
1.3 区间问题
1.4 练习
第 2 章 玩转双指针
2.1 算法解释
2.2 Two Sum
2.3 归并两个有序数组
2.4 滑动窗口
2.5 快慢指针
2.6 练习
第 3 章 居合斩!二分查找
3.1 算法解释
3.2 求开方
3.3 查找区间
3.4 查找峰值
3.5 旋转数组查找数字
3.6 练习
第 4 章 千奇百怪的排序算法
4.1 常用排序算法
4.2 快速选择
4.3 桶排序
4.4 练习
第 5 章 一切皆可搜索
5.1 算法解释
5.2 深度优先搜索
5.3 回溯法
5.4 广度优先搜索
5.5 练习
第 6 章 深入浅出动态规划
6.1 算法解释
6.2 基本动态规划:一维
6.3 基本动态规划:二维
6.4 分割类型题
6.5 子序列问题
6.6 背包问题
6.7 字符串编辑
6.8 股票交易
6.9 练习
第 7 章 化繁为简的分治法
7.1 算法解释
7.2 表达式问题
7.3 练习
第 8 章 巧解数学问题
8.1 引言
8.2 公倍数与公因数
8.3 质数
8.4 数字处理
8.5 随机与取样
8.6 练习
第 9 章 神奇的位运算
9.1 常用技巧
9.2 位运算基础问题
9.3 二进制特性
9.4 练习
第 10 章 妙用数据结构
10.1 C++ STL
10.2 Python 常用数据结构
10.3 数组
10.4 栈和队列
10.5 单调栈
10.6 优先队列
10.7 双端队列
10.8 哈希表
10.9 多重集合和映射
10.10 前缀和与积分图
10.11 练习
第 11 章 令人头大的字符串
11.1 引言
11.2 字符串比较
11.3 字符串理解
11.4 字符串匹配
11.5 练习
第 12 章 指针三剑客之一:链表
12.1 数据结构介绍
12.2 链表的基本操作
12.3 其它链表技巧
12.4 练习
第 13 章 指针三剑客之二:树
13.1 数据结构介绍
13.2 树的递归
13.3 层次遍历
13.4 前中后序遍历
13.5 二叉查找树
13.6 字典树
13.7 练习
第 14 章 指针三剑客之三:图
14.1 数据结构介绍
14.2 二分图
14.3 拓扑排序
14.4 练习
第 15 章 更加复杂的数据结构
15.1 引言
15.2 并查集
15.3 复合数据结构
15.4 练习
第16章 面试题
第 17 章 十大经典排序算法
README
本文档使用 MrDoc 发布
-
+
首页
6.4 分割类型题
# 6.4 分割类型题 ## [279. Perfect Squares](https://leetcode.com/problems/perfect-squares/) ### 题目描述 给定一个正整数,求其最少可以由几个完全平方数相加构成。 ### 输入输出样例 输入是给定的正整数,输出也是一个正整数,表示输入的数字最少可以由几个完全平方数相加构成。 ``` Input: n = 13 Output: 2 ``` 在这个样例中,13 的最少构成方法为 4+9。 ### 题解 对于分割类型题,动态规划的状态转移方程通常并不依赖相邻的位置,而是依赖于满足分割条件的位置。我们定义一个一维矩阵 dp,其中 dp[i] 表示数字 i 最少可以由几个完全平方数相加构成。在本题中,位置 i 只依赖 $$i - j^2$$ 的位置,如 i - 1、i - 4、i - 9 等等,才能满足完全平方分割的条件。因此 dp[i] 可以取的最小值即为 1+ min(dp[i-1], dp[i-4], dp[i-9] · · · )。注意边界条件的处理。 ```py class Solution: def numSquares(self, n: int) -> int: dp = [inf] * (n+1) dp[0] = 0 dp[1] = 1 for i in range(2,n+1): for j in range(1,isqrt(i)+1): dp[i] = min(dp[i], dp[i-j*j]+1) # 选或者不选 return dp[n] ``` ## [91. Decode Ways](https://leetcode.com/problems/decode-ways/) ### 题目描述 已知字母 A-Z 可以表示成数字 1-26。给定一个数字串,求有多少种不同的字符串等价于这个数字串。 ### 输入输出样例 输入是一个由数字组成的字符串,输出是满足条件的解码方式总数。 ``` Input: "226" Output: 3 ``` 在这个样例中,有三种解码方式:BZ(2 26)、VF(22 6) 或 BBF(2 2 6)。 ### 题解 这是一道很经典的动态规划题,难度不大但是十分考验耐心。这是因为只有 1-26 可以表示字母,因此对于一些特殊情况,比如数字 0 或者当相邻两数字大于 26 时,需要有不同的状态转移方程,详见如下代码。 ```math \left\{\begin{array}{l} f[i]=f[i-1], 1 \leqslant a \leqslant 9 \\ f[i]=f[i-2], 10 \leqslant b \leqslant 26 \\ f[i]=f[i-1]+f[i-2], 1 \leqslant a \leqslant 9,10 \leqslant b \leqslant 26 \end{array}\right. ``` ```py class Solution: def numDecodings(self, s: str) -> int: n = len(s) s = " " + s dp = [0] * (n + 1) dp[0] = 1 for i in range(1, n + 1): a = ord(s[i]) - ord("0") b = (ord(s[i - 1]) - ord("0")) * 10 + ord(s[i]) - ord("0") if 1 <= a <= 9: dp[i] = dp[i - 1] if 10 <= b <= 26: dp[i] += dp[i - 2] return dp[n] ``` ## [139. Word Break](https://leetcode.com/problems/word-break/) ### 题目描述 给定一个字符串和一个字符串集合,求是否存在一种分割方式,使得原字符串分割后的子字符串都可以在集合内找到。 ### 输入输出样例 ``` Input: s = "applepenapple", wordDict = ["apple", "pen"] Output: true ``` 在这个样例中,字符串可以被分割为 [“apple”,“pen”,“apple”]。 ### 题解 类似于完全平方数分割问题,这道题的分割条件由集合内的字符串决定,因此在考虑每个分割位置时,需要遍历字符串集合,以确定当前位置是否可以成功分割。注意对于位置 0,需要初始化值为真。 ```py class Solution: def wordBreak(self, s: str, wordDict: List[str]) -> bool: n = len(s) dp = [True] + [False] * n for i in range(1,n+1): for word in wordDict: m = len(word) if i >= m and s[i-m:i] == word: dp[i] = dp[i-m] if dp[i]: break return dp[n] ``` ## [1105. Filling Bookcase Shelves](https://leetcode.com/problems/filling-bookcase-shelves/) ### 题目描述 给定一个数组,每个元素代表一本书的厚度和高度。问对于一个固定宽度的书架,如果按照数组中书的顺序从左到右、从上到下摆放,最小总高度是多少。 ### 输入输出样例 ``` Input: books = [[1,1],[2,3],[2,3],[1,1],[1,1],[1,1],[1,2]], shelfWidth = 4 Output: 6 ```  ### 题解 令 dp[i] 表示放置第 i 本书时的最小总高度,则 dp[i] 可以是在第 i-1 本书下面重新放一排,也可以是在满足不超过前一排宽度的情况下放在前一排。 ```py class Solution: def minHeightShelves(self, books: List[List[int]], shelfWidth: int) -> int: n = len(books) dp = [0] * (n+1) for i in range(1, n+1): width, height = books[i-1] # 情况1,放在新的层 dp[i] = dp[i-1] + height # 情况2,放在同一层 total_width = width max_height = height for j in range(i-1, 0, -1): prev_width, prev_height = books[j-1] total_width += prev_width if total_width > shelfWidth: break max_height = max(max_height, prev_height) dp[i] = min(dp[i], dp[j-1] + max_height) return dp[n] ``` ## [377. Combination Sum IV](https://leetcode.com/problems/combination-sum-iv/) ### 题目描述 给定一个不重复数字的数组和一个目标数,求加起来是目标数的所有排列的总数量。(虽然这道题叫做 Combination Sum,但是不同顺序的组合会被当作不同答案,因此本质上是排列。) ### 输入输出样例 ``` Input: nums = [1,2,3], target = 4 Output: 7 ``` 七种不同的排列为 (1, 1, 1, 1)、(1, 1, 2)、(1, 2, 1)、(1, 3)、(2, 1, 1)、(2, 2) 和 (3, 1)。 ### 题解 令 dp[i] 表示加起来和为 i 时,满足条件的排列数量。在内循环中我们可以直接对所有合法数字进行拿取。 ```py class Solution: def combinationSum4(self, nums: List[int], target: int) -> int: dp = [1] + [0] * target for i in range(1, target+1): dp[i] = sum(dp[i-num] for num in nums if i >= num) return dp[target] ```
嘉心糖糖
2025年3月23日 21:32
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码