Skip to content

Commit 2da3dac

Browse files
Update
1 parent a21101f commit 2da3dac

9 files changed

+203
-18
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
* [KMP算法(代码篇)](https://www.bilibili.com/video/BV1M5411j7Xx)
2020
* [回溯算法(理论篇)](https://www.bilibili.com/video/BV1cy4y167mM)
2121
* [回溯算法之组合问题(力扣题目:77.组合)](https://www.bilibili.com/video/BV1ti4y1L7cv)
22+
* [带你学透回溯算法-组合问题的剪枝操作(对应力扣题目:77.组合)](https://www.bilibili.com/video/BV1wi4y157er)
2223

2324
(持续更新中....)
2425

@@ -241,6 +242,7 @@
241242
|[0056.合并区间](https://github.com/youngyangyang04/leetcode/blob/master/problems/0056.合并区间.md) |数组 |中等| **贪心** 以为是模拟题,其实是贪心|
242243
|[0057.插入区间](https://github.com/youngyangyang04/leetcode/blob/master/problems/0057.插入区间.md) |数组 |困难| **模拟** 是一道数组难题|
243244
|[0059.螺旋矩阵II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0059.螺旋矩阵II.md) |数组 |中等|**模拟**|
245+
|[0070.爬楼梯](https://github.com/youngyangyang04/leetcode/blob/master/problems/0070.爬楼梯.md) |动态规划|简单|**动态规划** dp里求排列|
244246
|[0077.组合](https://github.com/youngyangyang04/leetcode/blob/master/problems/0077.组合.md) |回溯 |中等|**回溯**|
245247
|[0078.子集](https://github.com/youngyangyang04/leetcode/blob/master/problems/0078.子集.md) |回溯/数组 |中等|**回溯**|
246248
|[0083.删除排序链表中的重复元素](https://github.com/youngyangyang04/leetcode/blob/master/problems/0083.删除排序链表中的重复元素.md) |链表 |简单|**模拟**|
@@ -304,6 +306,7 @@
304306
|[0347.前K个高频元素](https://github.com/youngyangyang04/leetcode/blob/master/problems/0347.前K个高频元素.md) |哈希/堆/优先级队列 |中等| **哈希/优先级队列**|
305307
|[0349.两个数组的交集](https://github.com/youngyangyang04/leetcode/blob/master/problems/0349.两个数组的交集.md) |哈希表 |简单|**哈希**|
306308
|[0350.两个数组的交集II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0350.两个数组的交集II.md) |哈希表 |简单|**哈希**|
309+
|[0377.组合总和Ⅳ](https://github.com/youngyangyang04/leetcode/blob/master/problems/0377.组合总和Ⅳ.md) |动态规划 |中等|**完全背包** 求排列|
307310
|[0383.赎金信](https://github.com/youngyangyang04/leetcode/blob/master/problems/0383.赎金信.md) |数组 |简单|**暴力** **字典计数** **哈希**|
308311
|[0404.左叶子之和](https://github.com/youngyangyang04/leetcode/blob/master/problems/0404.左叶子之和.md) |树/二叉树 |简单|**递归** **迭代**|
309312
|[0406.根据身高重建队列](https://github.com/youngyangyang04/leetcode/blob/master/problems/0406.根据身高重建队列.md) |树/二叉树 |简单|**递归** **迭代**|
@@ -323,6 +326,7 @@
323326
|[0501.二叉搜索树中的众数](https://github.com/youngyangyang04/leetcode/blob/master/problems/0501.二叉搜索树中的众数.md) |二叉树 |简单|**递归/中序遍历**|
324327
|[0513.找树左下角的值](https://github.com/youngyangyang04/leetcode/blob/master/problems/0513.找树左下角的值.md) |二叉树 |中等|**递归** **迭代**|
325328
|[0515.在每个树行中找最大值](https://github.com/youngyangyang04/leetcode/blob/master/problems/0515.在每个树行中找最大值.md) |二叉树 |简单|**广度优先搜索/队列**|
329+
|[0518.零钱兑换II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0518.零钱兑换II.md) |动态规划 |中等|**动态规划** dp里求组合|
326330
|[0530.二叉搜索树的最小绝对差](https://github.com/youngyangyang04/leetcode/blob/master/problems/0530.二叉搜索树的最小绝对差.md) |二叉树搜索树 |简单|**递归** **迭代**|
327331
|[0538.把二叉搜索树转换为累加树](https://github.com/youngyangyang04/leetcode/blob/master/problems/0538.把二叉搜索树转换为累加树.md) |二叉搜索树 |简单|**递归** **迭代**|
328332
|[0541.反转字符串II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0541.反转字符串II.md) |字符串 |简单| **模拟**|

problems/0055.跳跃游戏.md

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
## 链接
2-
https://leetcode-cn.com/problems/jump-game/
1+
2+
> 通知
33
44
# 55. 跳跃游戏
55

6+
题目链接:https://leetcode-cn.com/problems/jump-game/
7+
68
给定一个非负整数数组,你最初位于数组的第一个位置。
79

810
数组中的每个元素代表你在该位置可以跳跃的最大长度。
@@ -24,18 +26,19 @@ https://leetcode-cn.com/problems/jump-game/
2426

2527
刚看到本题一开始可能想:当前位置元素如果是3,我究竟是跳一步呢,还是两步呢,还是三步呢,究竟跳几步才是最优呢?
2628

27-
可以转变一下思路,不一样非要明确一次究竟跳几步,每次取最大的跳跃步数,这个就是可以跳跃的覆盖范围。
29+
其实跳几步无所谓,关键在于可跳的覆盖范围!
2830

29-
这个范围内,已经是可以跳过来的,别管是怎么跳的,反正一定可以跳过来
31+
不一定非要明确一次究竟跳几步,每次取最大的跳跃步数,这个就是可以跳跃的覆盖范围
3032

31-
**那么就是这个跳跃覆盖范围究竟可不可以覆盖到终点!**
33+
这个范围内,别管是怎么跳的,反正一定可以跳过来。
3234

33-
每次移动取最大跳跃步数,得到最大的覆盖范围,每移动一个单位,就更新最大覆盖范围。
35+
**那么这个问题就转化为跳跃覆盖范围究竟可不可以覆盖到终点!**
3436

35-
**局部最优解:每次取最大跳跃步数(取最大覆盖范围),整体最优解:最后得到就是整体最大覆盖范围,看是否能到终点**
37+
每次移动取最大跳跃步数(得到最大的覆盖范围),每移动一个单位,就更新最大覆盖范围。
3638

39+
**贪心算法局部最优解:每次取最大跳跃步数(取最大覆盖范围),整体最优解:最后得到整体最大覆盖范围,看是否能到终点**
3740

38-
那么我们每次取最大的覆盖范围,看最后能否覆盖终点。
41+
局部最优推出全局最优,找不出反例,试试贪心!
3942

4043
如图:
4144

@@ -45,11 +48,11 @@ i每次移动只能在cover的范围内移动,每移动一个元素,cover得
4548

4649
而cover每次只取 max(该元素数值补充后的范围, cover本身范围)。
4750

48-
如果cover大于等于了终点下表,直接return true就可以了。
51+
如果cover大于等于了终点下标,直接return true就可以了。
4952

5053
C++代码如下:
5154

52-
```
55+
```C++
5356
class Solution {
5457
public:
5558
bool canJump(vector<int>& nums) {
@@ -65,6 +68,12 @@ public:
6568
```
6669
# 总结
6770
71+
这道题目关键点在于:不用拘泥于每次究竟跳跳几步,而是看覆盖范围,覆盖范围内已经是可以跳过来的,不用管是怎么跳的。
72+
73+
大家可以看出思路想出来了,代码还是非常简单的。
74+
75+
一些同学可能感觉,我在讲贪心系列的时候,题目和题目之间貌似没有什么联系?
6876
77+
**是真的就是没什么联系,因为贪心无套路!**没有个整体的贪心框架解决一些列问题,只能是接触各种类型的题目锻炼自己的贪心思维!
6978
70-
其实贪心和动态规划很容易混在一起,在面试中,我们应该本着能用贪心就用贪心,贪心解决不了再考虑用动态规划。 毕竟贪心更容易理解,并快速写出代码。
79+
就酱,「代码随想录」值得推荐给身边的朋友同学们!

problems/0070.爬楼梯.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
dp里求排列,1 2 步 和 2 1 步都是上三个台阶,但不一样!
3+
4+
这是求排列
5+
```
6+
class Solution {
7+
public:
8+
int climbStairs(int n) {
9+
vector<int> dp(n + 1, 0);
10+
dp[0] = 1;
11+
for (int i = 1; i <= n; i++) {
12+
for (int j = 1; j <= 2; j++) {
13+
if (i - j >= 0) dp[i] += dp[i - j];
14+
}
15+
}
16+
return dp[n];
17+
}
18+
};
19+
```

problems/0122.买卖股票的最佳时机II.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ public:
126126

127127
就酱,「代码随想录」是技术公众号里的一抹清流,值得推荐给你的朋友同学们!
128128

129+
> **我是[程序员Carl](https://github.com/youngyangyang04),可以找我[组队刷题](https://img-blog.csdnimg.cn/20201115103410182.png),也可以在[B站上找到我](https://space.bilibili.com/525438321),本文[leetcode刷题攻略](https://github.com/youngyangyang04/leetcode-master)已收录,更多[精彩算法文章](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzUxNjY5NTYxNA==&action=getalbum&album_id=1485825793120387074&scene=173#wechat_redirect)尽在公众号:[代码随想录](https://img-blog.csdnimg.cn/20201124161234338.png),关注后就会发现和「代码随想录」相见恨晚!**
130+
131+
**如果感觉题解对你有帮助,不要吝啬给一个👍吧!**
132+
129133

130-
> 我是[程序员Carl](https://github.com/youngyangyang04),组队刷题可以找我,本文[leetcode刷题攻略](https://github.com/youngyangyang04/leetcode-master)已收录,更多[精彩算法文章](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzUxNjY5NTYxNA==&action=getalbum&album_id=1485825793120387074&scene=173#wechat_redirect)尽在:[代码随想录](https://img-blog.csdnimg.cn/20200815195519696.png),期待你的关注!
131134

problems/0279.完全平方数.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
没有问你组合方式,而是问你最小个数
2+
3+
// 组合的逻辑
4+
```
5+
class Solution {
6+
public:
7+
int numSquares(int n) {
8+
vector<int> sum;
9+
for (int i = 1; i * i <= n; i++) {
10+
sum.push_back(i * i);
11+
}
12+
vector<int> dp(n + 1, INT_MAX);
13+
dp[0] = 0;
14+
for (int i = 0; i < sum.size(); i++) {
15+
for (int j = 1; j <= n; j++) {
16+
if (j - sum[i] >= 0 && dp[j - sum[i]] != INT_MAX) {
17+
dp[j] = min(dp[j - sum[i]] + 1, dp[j]);
18+
}
19+
}
20+
}
21+
return dp[n];
22+
}
23+
};
24+
```
25+
26+
27+
// 排列的逻辑
28+
```
29+
class Solution {
30+
public:
31+
int numSquares(int n) {
32+
vector<int> dp(n + 1, 0);
33+
for (int i = 0; i <= n; i++) {
34+
dp[i] = i; // 最多也就是i都是1组成的情况
35+
for (int j = 1; j * j <= i; j++) {
36+
dp[i] = min(dp[i - j * j] + 1, dp[i]);
37+
}
38+
}
39+
return dp[n];
40+
}
41+
};
42+
```

problems/0322.零钱兑换.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ public:
2020
if (dp[i] == 0) dp[i] = dp[i - coins[j]] + 1;
2121
else dp[i] = min(dp[i - coins[j]] + 1, dp[i]);
2222
}
23-
24-
2523
}
2624
//for (int k = 0 ; k<= amount; k++) {
2725
// cout << dp[k] << " ";
@@ -35,6 +33,28 @@ public:
3533
};
3634
```
3735

36+
我用求组合的思路也过了,
37+
```
38+
class Solution {
39+
public:
40+
int coinChange(vector<int>& coins, int amount) {
41+
//int dp[10003] = {0}; // 并没有给所有元素赋值0
42+
//if (amount == 0) return 0;
43+
vector<int> dp(10003, INT_MAX);
44+
dp[0] = 0;
45+
for (int i = 0 ;i < coins.size(); i++) { // 求组合
46+
for (int j = 1; j <= amount; j++) {
47+
if (j - coins[i] >= 0 && dp[j - coins[i]] != INT_MAX) {
48+
dp[j] = min(dp[j - coins[i]] + 1, dp[j]);
49+
}
50+
}
51+
}
52+
if (dp[amount] == INT_MAX) return -1;
53+
return dp[amount];
54+
}
55+
};
56+
```
57+
3858
这种标记d代码简短,但思路有点绕
3959
```
4060
class Solution {

problems/0377.组合总和Ⅳ.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
和之前个回溯法的各个总和串起来一波,本题用回溯稳稳的超时
3+
4+
```
5+
class Solution {
6+
public:
7+
int combinationSum4(vector<int>& nums, int target) {
8+
vector<int> dp(target + 1, 0);
9+
dp[0] = 1;
10+
for (int i = 0; i <= target; i++) {
11+
for (int j = 0; j < nums.size(); j++) {
12+
if (i - nums[j] >= 0) {
13+
dp[i] += dp[i - nums[j]];
14+
}
15+
}
16+
}
17+
return dp[target];
18+
}
19+
};
20+
```
21+
22+
23+
C++测试用例有超过两个树相加超过int的数据
24+
超限的情况
25+
26+
27+
一些题解会直接用ull usigned long long
28+
29+
java 也是四个字节,理论上没有差别,可能后台java和C++测试用例不同,bug.....
30+
```
31+
class Solution {
32+
public:
33+
int combinationSum4(vector<int>& nums, int target) {
34+
vector<int> dp(target + 1, 0);
35+
dp[0] = 1;
36+
for (int i = 0; i <= target; i++) {
37+
for (int num : nums) {
38+
if (i - num >= 0 && dp[i] < INT_MAX - dp[i - num]) {
39+
dp[i] += dp[i - num];
40+
}
41+
}
42+
}
43+
return dp[target];
44+
}
45+
};
46+
```

problems/0474.一和零.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11

2-
搞不懂 leetcode后台是什么牛逼的编译器,初始化int dp[101][101] = {0}; 可以 ,int dp[101][101];就不行,有其他默认值,坑死。
3-
代码我做了实验,后台会拿findMaxForm,运行两次,取第二次的结果,dp有上次记录的数值。
4-
5-
```
62
// 即使做了很多动态规划的题目,做这个依然懵逼
73
// 这道题目有点 程序员自己给自己出难进急转弯的意思
84
// 该子集中 最多 有 m 个 0 和 n 个 1 。 指的是整体子集
95
// 这是二维背包,多重背包
106
// dp[i][j] 有i个0,j个1最大有多少个子集,但是遍历的时候 顶部是哪里呢?
7+
8+
搞不懂 leetcode后台是什么牛逼的编译器,初始化int dp[101][101] = {0}; 可以 ,int dp[101][101];就不行,有其他默认值,坑死。
9+
代码我做了实验,后台会拿findMaxForm,运行两次,取第二次的结果,dp有上次记录的数值。
10+
11+
```
1112
class Solution {
1213
public:
1314
int findMaxForm(vector<string>& strs, int m, int n) {

problems/0518.零钱兑换II.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
2+
// 计算有多少种方式
3+
// 完全背包 for循环的顺序啊,先是哪个for 后是哪个for定不下来
4+
5+
排列
6+
```
7+
class Solution {
8+
public:
9+
int change(int amount, vector<int>& coins) {
10+
int dp[50001] = {0};
11+
dp[0] = 1;
12+
for (int i = 0; i <= amount; i++) {
13+
for (int j = 0; j < coins.size(); j++) { // 这是组合把???
14+
if (i - coins[j] >= 0) dp[i] += dp[i - coins[j]];
15+
}
16+
for (int j = 0; j <= amount; j++) {
17+
cout << dp[j] << " ";
18+
}
19+
cout << endl;
20+
}
21+
return dp[amount];
22+
}
23+
};
24+
```
25+
26+
这个才是组合,本题的题解,
27+
```
28+
class Solution {
29+
public:
30+
int change(int amount, vector<int>& coins) {
31+
int dp[50001] = {0};
32+
dp[0] = 1;
33+
for (int i = 0; i < coins.size(); i++) { // 一个钱币只在序列里出现一次
34+
for (int j = 0; j <= amount; j++) {
35+
if (j - coins[i] >= 0) dp[j] += dp[j - coins[i]];
36+
}
37+
}
38+
return dp[amount];
39+
}
40+
};
41+
```

0 commit comments

Comments
 (0)