替换图片链接
This commit is contained in:
@@ -254,5 +254,5 @@ traversal(cur->left, tmp, result);
|
||||
* Github:[leetcode-master](https://github.com/youngyangyang04/leetcode-master)
|
||||
* 知乎:[代码随想录](https://www.zhihu.com/people/sun-xiu-yang-64)
|
||||
|
||||

|
||||

|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -31,7 +31,7 @@ for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target;
|
||||
|
||||
在[回溯算法:求组合总和(二)](https://programmercarl.com/0039.组合总和.html)第一个树形结构没有画出startIndex的作用,**这里这里纠正一下,准确的树形结构如图所示:**
|
||||
|
||||

|
||||

|
||||
|
||||
## 周二
|
||||
|
||||
@@ -45,7 +45,7 @@ for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target;
|
||||
|
||||
都知道组合问题可以抽象为树形结构,那么“使用过”在这个树形结构上是有两个维度的,一个维度是同一树枝上“使用过”,一个维度是同一树层上“使用过”。**没有理解这两个层面上的“使用过” 是造成大家没有彻底理解去重的根本原因**。
|
||||
|
||||

|
||||

|
||||
|
||||
我在图中将used的变化用橘黄色标注上,可以看出在candidates[i] == candidates[i - 1]相同的情况下:
|
||||
|
||||
@@ -79,7 +79,7 @@ for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target;
|
||||
|
||||
**本题的树形结构中,和代码的逻辑有一个小出入,已经判断不是回文的子串就不会进入递归了,纠正如下:**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## 周四
|
||||
@@ -90,7 +90,7 @@ for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target;
|
||||
|
||||
树形图如下:
|
||||
|
||||

|
||||

|
||||
|
||||
在本文的树形结构图中,我已经把详细的分析思路都画了出来,相信大家看了之后一定会思路清晰不少!
|
||||
|
||||
@@ -112,7 +112,7 @@ if (s.size() > 12) return result; // 剪枝
|
||||
|
||||
如图:
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
认清这个本质之后,今天的题目就是一道模板题了。
|
||||
|
||||
@@ -11,14 +11,14 @@
|
||||
|
||||
树形结构如下:
|
||||
|
||||

|
||||

|
||||
|
||||
## 周二
|
||||
|
||||
在[回溯算法:递增子序列](https://programmercarl.com/0491.递增子序列.html)中,处处都能看到子集的身影,但处处是陷阱,值得好好琢磨琢磨!
|
||||
|
||||
树形结构如下:
|
||||

|
||||

|
||||
|
||||
[回溯算法:递增子序列](https://programmercarl.com/0491.递增子序列.html)留言区大家有很多疑问,主要还是和[回溯算法:求子集问题(二)](https://programmercarl.com/0090.子集II.html)混合在了一起。
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
可以看出元素1在[1,2]中已经使用过了,但是在[2,1]中还要在使用一次1,所以处理排列问题就不用使用startIndex了。
|
||||
|
||||
如图:
|
||||

|
||||

|
||||
|
||||
**大家此时可以感受出排列问题的不同:**
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
树形结构如下:
|
||||
|
||||

|
||||

|
||||
|
||||
**这道题目神奇的地方就是used[i - 1] == false也可以,used[i - 1] == true也可以!**
|
||||
|
||||
@@ -54,11 +54,11 @@
|
||||
|
||||
树层上去重(used[i - 1] == false),的树形结构如下:
|
||||
|
||||

|
||||

|
||||
|
||||
树枝上去重(used[i - 1] == true)的树型结构如下:
|
||||
|
||||

|
||||

|
||||
|
||||
**可以清晰的看到使用(used[i - 1] == false),即树层去重,效率更高!**
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
如图:
|
||||
|
||||

|
||||

|
||||
|
||||
## 周二
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
如图:
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## 周三
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
如图:
|
||||
|
||||

|
||||

|
||||
|
||||
注意:**图中的移动下标是到当前这步覆盖的最远距离(下标2的位置),此时没有到终点,只能增加第二步来扩大覆盖范围**。
|
||||
|
||||
@@ -55,10 +55,10 @@
|
||||
而版本二就比较统一的,超过范围,步数就加一,但在移动下标的范围了做了文章。
|
||||
|
||||
即如果覆盖最远距离下标是倒数第二点:直接加一就行,默认一定可以到终点。如图:
|
||||

|
||||

|
||||
|
||||
如果覆盖最远距离下标不是倒数第二点,说明本次覆盖已经到终点了。如图:
|
||||

|
||||

|
||||
|
||||
有的录友认为版本一好理解,有的录友认为版本二好理解,其实掌握一种就可以了,也不用非要比拼一下代码的简洁性,简洁程度都差不多了。
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
文中从计算机硬件出发,分析计算机的计算性能,然后亲自做实验,整理出数据如下:
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
**大家有一个数量级上的概念就可以了!**
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
如图:
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
接着在贪心另一边,左孩子大于右孩子,左孩子的糖果就要比右孩子多。
|
||||
@@ -50,7 +50,7 @@
|
||||
局部最优可以推出全局最优。
|
||||
|
||||
如图:
|
||||

|
||||

|
||||
|
||||
|
||||
## 周三
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
如图:
|
||||
|
||||

|
||||

|
||||
|
||||
模拟射气球的过程,很多同学真的要去模拟了,实时把气球从数组中移走,这么写的话就复杂了,从前向后遍历重复的只要跳过就可以的。
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
如图:
|
||||
|
||||

|
||||

|
||||
|
||||
细心的同学就发现了,此题和 [贪心算法:用最少数量的箭引爆气球](https://programmercarl.com/0452.用最少数量的箭引爆气球.html)非常像。
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
|
||||
如图:
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## 周四
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
|
||||
如图:
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## 总结
|
||||
|
||||
@@ -31,7 +31,7 @@ for (int i = 1; i < m; i++) {
|
||||
}
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## 周二
|
||||
@@ -45,7 +45,7 @@ dp[i][j]定义依然是:表示从(0 ,0)出发,到(i, j) 有dp[i][j]条
|
||||
|
||||
如图:
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
这里难住了不少同学,代码如下:
|
||||
@@ -70,11 +70,11 @@ for (int i = 1; i < m; i++) {
|
||||
|
||||
拿示例1来举例如题:
|
||||
|
||||

|
||||

|
||||
|
||||
对应的dp table 如图:
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## 周三
|
||||
@@ -111,7 +111,7 @@ for (int i = 3; i <= n ; i++) {
|
||||
|
||||
举例当n为10 的时候,dp数组里的数值,如下:
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ dp数组如何初始化:只需要初始化dp[0]就可以了,推导的基础
|
||||
|
||||
n为5时候的dp数组状态如图:
|
||||
|
||||

|
||||

|
||||
|
||||
## 总结
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
关于其他几种常用的背包,大家看这张图就了然于胸了:
|
||||
|
||||

|
||||

|
||||
|
||||
本文用动规五部曲详细讲解了01背包的二维dp数组的实现方法,大家其实可以发现最简单的是推导公式了,推导公式估计看一遍就记下来了,但难就难在确定初始化和遍历顺序上。
|
||||
|
||||
@@ -70,7 +70,7 @@ for(int i = 1; i < weight.size(); i++) { // 遍历物品
|
||||
|
||||
来看一下对应的dp数组的数值,如图:
|
||||
|
||||

|
||||

|
||||
|
||||
最终结果就是dp[2][4]。
|
||||
|
||||
@@ -122,7 +122,7 @@ for(int i = 0; i < weight.size(); i++) { // 遍历物品
|
||||
|
||||
一维dp,分别用物品0,物品1,物品2 来遍历背包,最终得到结果如下:
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## 周三
|
||||
|
||||
@@ -35,7 +35,7 @@ bagSize = (S + sum) / 2 = (3 + 5) / 2 = 4
|
||||
|
||||
dp数组状态变化如下:
|
||||
|
||||

|
||||

|
||||
|
||||
## 周二
|
||||
|
||||
@@ -73,7 +73,7 @@ dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);
|
||||
最后dp数组的状态如下所示:
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
## 周三
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ dp[1] = max(nums[0], nums[1]);
|
||||
|
||||
以示例二,输入[2,7,9,3,1]为例。
|
||||
|
||||

|
||||

|
||||
|
||||
红框dp[nums.size() - 1]为结果。
|
||||
|
||||
@@ -42,15 +42,15 @@ dp[1] = max(nums[0], nums[1]);
|
||||
|
||||
* 情况一:考虑不包含首尾元素
|
||||
|
||||

|
||||

|
||||
|
||||
* 情况二:考虑包含首元素,不包含尾元素
|
||||
|
||||

|
||||

|
||||
|
||||
* 情况三:考虑包含尾元素,不包含首元素
|
||||
|
||||

|
||||

|
||||
|
||||
需要注意的是,**“考虑” 不等于 “偷”**,例如情况三,虽然是考虑包含尾元素,但不一定要选尾部元素!对于情况三,取nums[1] 和 nums[3]就是最大的。
|
||||
|
||||
@@ -178,7 +178,7 @@ return {val2, val1};
|
||||
|
||||
以示例1为例,dp数组状态如下:(**注意用后序遍历的方式推导**)
|
||||
|
||||

|
||||

|
||||
|
||||
**最后头结点就是 取下标0 和 下标1的最大值就是偷得的最大金钱**。
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ dp[0][4] = 0;
|
||||
|
||||
以输入[1,2,3,4,5]为例
|
||||
|
||||

|
||||

|
||||
|
||||
可以看到红色框为最后两次卖出的状态。
|
||||
|
||||
@@ -144,7 +144,7 @@ for (int j = 1; j < 2 * k; j += 2) {
|
||||
以输入[1,2,3,4,5],k=2为例。
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
最后一次卖出,一定是利润最大的,dp[prices.size() - 1][2 * k]即红色部分就是最后求解。
|
||||
|
||||
@@ -197,7 +197,7 @@ vector<vector<int>> dp(n, vector<int>(3, 0));
|
||||
以 [1,2,3,0,2] 为例,dp数组如下:
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
最后两个状态 不持有股票(能购买) 和 不持有股票(冷冻期)都有可能最后结果,取最大的。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user