mirror of
https://github.com/krahets/hello-algo.git
synced 2024-12-26 01:06:28 +08:00
build
This commit is contained in:
parent
4037b872f4
commit
7ba648cfdc
7 changed files with 14 additions and 14 deletions
|
@ -6,7 +6,7 @@ comments: true
|
|||
|
||||
!!! question
|
||||
|
||||
给定一棵二叉树的前序遍历 `preorder` 和中序遍历 `inorder` ,请从中构建二叉树,返回二叉树的根节点。假设二叉树中没有值重复的节点。
|
||||
给定一棵二叉树的前序遍历 `preorder` 和中序遍历 `inorder` ,请从中构建二叉树,返回二叉树的根节点。假设二叉树中没有值重复的节点,如图 12-5 所示。
|
||||
|
||||
![构建二叉树的示例数据](build_binary_tree_problem.assets/build_tree_example.png){ class="animation-figure" }
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ comments: true
|
|||
- 0-1 背包的状态定义为前 $i$ 个物品在剩余容量为 $c$ 的背包中的最大价值。根据不放入背包和放入背包两种决策,可得到最优子结构,并构建出状态转移方程。在空间优化中,由于每个状态依赖正上方和左上方的状态,因此需要倒序遍历列表,避免左上方状态被覆盖。
|
||||
- 完全背包问题的每种物品的选取数量无限制,因此选择放入物品的状态转移与 0-1 背包问题不同。由于状态依赖正上方和正左方的状态,因此在空间优化中应当正序遍历。
|
||||
- 零钱兑换问题是完全背包问题的一个变种。它从求“最大”价值变为求“最小”硬币数量,因此状态转移方程中的 $\max()$ 应改为 $\min()$ 。从追求“不超过”背包容量到追求“恰好”凑出目标金额,因此使用 $amt + 1$ 来表示“无法凑出目标金额”的无效解。
|
||||
- 零钱兑换 II 问题从求“最少硬币数量”改为求“硬币组合数量”,状态转移方程相应地从 $\min()$ 改为求和运算符。
|
||||
- 零钱兑换问题 II 从求“最少硬币数量”改为求“硬币组合数量”,状态转移方程相应地从 $\min()$ 改为求和运算符。
|
||||
|
||||
**编辑距离问题**
|
||||
|
||||
|
|
|
@ -298,7 +298,7 @@ comments: true
|
|||
|
||||
## 15.1.1 贪心算法的优点与局限性
|
||||
|
||||
**贪心算法不仅操作直接、实现简单,而且通常效率也很高**。在以上代码中,记硬币最小面值为 $\min(coins)$ ,则贪心选择最多循环 $amt / \min(coins)$ 次,时间复杂度为 $O(amt / \min(coins))$ 。这比动态规划解法的时间复杂度 $O(n \times amt)$ 降低了一个数量级。
|
||||
**贪心算法不仅操作直接、实现简单,而且通常效率也很高**。在以上代码中,记硬币最小面值为 $\min(coins)$ ,则贪心选择最多循环 $amt / \min(coins)$ 次,时间复杂度为 $O(amt / \min(coins))$ 。这比动态规划解法的时间复杂度 $O(n \times amt)$ 小了一个数量级。
|
||||
|
||||
然而,**对于某些硬币面值组合,贪心算法并不能找到最优解**。图 15-2 给出了两个示例。
|
||||
|
||||
|
|
|
@ -1344,7 +1344,7 @@ comments: true
|
|||
|
||||
然而,**线性探测容易产生“聚集现象”**。具体来说,数组中连续被占用的位置越长,这些连续位置发生哈希冲突的可能性越大,从而进一步促使该位置的聚堆生长,形成恶性循环,最终导致增删查改操作效率劣化。
|
||||
|
||||
值得注意的是,**我们不能在开放寻址哈希表中直接删除元素**。这是因为删除元素会在数组内产生一个空桶 `None` ,而当查询元素时,线性探测到该空桶就会返回,因此在该空桶之下的元素都无法再被访问到,程序可能误判这些元素不存在。
|
||||
值得注意的是,**我们不能在开放寻址哈希表中直接删除元素**。这是因为删除元素会在数组内产生一个空桶 `None` ,而当查询元素时,线性探测到该空桶就会返回,因此在该空桶之下的元素都无法再被访问到,程序可能误判这些元素不存在,如图 6-7 所示。
|
||||
|
||||
![在开放寻址中删除元素导致的查询问题](hash_collision.assets/hash_table_open_addressing_deletion.png){ class="animation-figure" }
|
||||
|
||||
|
|
|
@ -228,7 +228,7 @@ $$
|
|||
T(h) = 2^0h + 2^1(h-1) + 2^2(h-2) + \dots + 2^{(h-1)}\times1
|
||||
$$
|
||||
|
||||
化简上式需要借助中学的数列知识,将对 $T(h)$ 乘以 $2$ ,得到:
|
||||
化简上式需要借助中学的数列知识,先将 $T(h)$ 乘以 $2$ ,得到:
|
||||
|
||||
$$
|
||||
\begin{aligned}
|
||||
|
|
|
@ -18,14 +18,14 @@ comments: true
|
|||
|
||||
<div class="center-table" markdown>
|
||||
|
||||
| 方法名 | 描述 | 时间复杂度 |
|
||||
| ------------- | ---------------- | ---------- |
|
||||
| `pushFirst()` | 将元素添加至队首 | $O(1)$ |
|
||||
| `pushLast()` | 将元素添加至队尾 | $O(1)$ |
|
||||
| `popFirst()` | 删除队首元素 | $O(1)$ |
|
||||
| `popLast()` | 删除队尾元素 | $O(1)$ |
|
||||
| `peekFirst()` | 访问队首元素 | $O(1)$ |
|
||||
| `peekLast()` | 访问队尾元素 | $O(1)$ |
|
||||
| 方法名 | 描述 | 时间复杂度 |
|
||||
| -------------- | ---------------- | ---------- |
|
||||
| `push_first()` | 将元素添加至队首 | $O(1)$ |
|
||||
| `push_last()` | 将元素添加至队尾 | $O(1)$ |
|
||||
| `pop_first()` | 删除队首元素 | $O(1)$ |
|
||||
| `pop_last()` | 删除队尾元素 | $O(1)$ |
|
||||
| `peek_first()` | 访问队首元素 | $O(1)$ |
|
||||
| `peek_last()` | 访问队尾元素 | $O(1)$ |
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ hide:
|
|||
|
||||
两年前,我在力扣上分享了“剑指 Offer”系列题解,受到了许多同学的喜爱和支持。在与读者交流期间,我最常收到的一个问题是“如何入门算法”。逐渐地,我对这个问题产生了浓厚的兴趣。
|
||||
|
||||
两眼一抹黑地刷题似乎是最受欢迎的方法,简单直接且有效。然而刷题就如同玩“扫雷”游戏,自学能力强的同学能够顺利将地雷逐个排掉,而基础不足的同学很可能被炸的满头是包,并在挫折中步步退缩。通读教材也是一种常见做法,但对于面向求职的同学来说,毕业季、投递简历、准备笔试面试已经消耗了大部分精力,啃厚重的书往往变成了一项艰巨的挑战。
|
||||
两眼一抹黑地刷题似乎是最受欢迎的方法,简单直接且有效。然而刷题就如同玩“扫雷”游戏,自学能力强的同学能够顺利将地雷逐个排掉,而基础不足的同学很可能被炸得满头是包,并在挫折中步步退缩。通读教材也是一种常见做法,但对于面向求职的同学来说,毕业季、投递简历、准备笔试面试已经消耗了大部分精力,啃厚重的书往往变成了一项艰巨的挑战。
|
||||
|
||||
如果你也面临类似的困扰,那么很幸运这本书找到了你。本书是我对这个问题给出的答案,即使不是最优解,也至少是一次积极的尝试。本书虽然不足以让你直接拿到 Offer ,但会引导你探索数据结构与算法的“知识地图”,带你了解不同“地雷”的形状、大小和分布位置,让你掌握各种“排雷方法”。有了这些本领,相信你可以更加自如地刷题和阅读文献,逐步构建起完整的知识体系。
|
||||
|
||||
|
|
Loading…
Reference in a new issue