mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-08 00:43:04 +08:00
Merge branch 'master' of github.com:youngyangyang04/leetcode-master
This commit is contained in:
@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
## 数字和字母如何映射
|
## 数字和字母如何映射
|
||||||
|
|
||||||
可以使用map或者定义一个二位数组,例如:string letterMap[10],来做映射,我这里定义一个二维数组,代码如下:
|
可以使用map或者定义一个二维数组,例如:string letterMap[10],来做映射,我这里定义一个二维数组,代码如下:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const string letterMap[10] = {
|
const string letterMap[10] = {
|
||||||
|
@ -50,15 +50,15 @@
|
|||||||
|
|
||||||
采用二分法来去寻找左右边界,为了让代码清晰,我分别写两个二分来寻找左边界和右边界。
|
采用二分法来去寻找左右边界,为了让代码清晰,我分别写两个二分来寻找左边界和右边界。
|
||||||
|
|
||||||
**刚刚接触二分搜索的同学不建议上来就像如果用一个二分来查找左右边界,很容易把自己绕进去,建议扎扎实实的写两个二分分别找左边界和右边界**
|
**刚刚接触二分搜索的同学不建议上来就想用一个二分来查找左右边界,很容易把自己绕进去,建议扎扎实实的写两个二分分别找左边界和右边界**
|
||||||
|
|
||||||
### 寻找右边界
|
### 寻找右边界
|
||||||
|
|
||||||
先来寻找右边界,至于二分查找,如果看过[704.二分查找](https://programmercarl.com/0704.二分查找.html)就会知道,二分查找中什么时候用while (left <= right),有什么时候用while (left < right),其实只要清楚**循环不变量**,很容易区分两种写法。
|
先来寻找右边界,至于二分查找,如果看过[704.二分查找](https://programmercarl.com/0704.二分查找.html)就会知道,二分查找中什么时候用while (left <= right),有什么时候用while (left < right),其实只要清楚**循环不变量**,很容易区分两种写法。
|
||||||
|
|
||||||
那么这里我采用while (left <= right)的写法,区间定义为[left, right],即左闭又闭的区间(如果这里有点看不懂了,强烈建议把[704.二分查找](https://programmercarl.com/0704.二分查找.html)这篇文章先看了,704题目做了之后再做这道题目就好很多了)
|
那么这里我采用while (left <= right)的写法,区间定义为[left, right],即左闭右闭的区间(如果这里有点看不懂了,强烈建议把[704.二分查找](https://programmercarl.com/0704.二分查找.html)这篇文章先看了,704题目做了之后再做这道题目就好很多了)
|
||||||
|
|
||||||
确定好:计算出来的右边界是不包好target的右边界,左边界同理。
|
确定好:计算出来的右边界是不包含target的右边界,左边界同理。
|
||||||
|
|
||||||
可以写出如下代码
|
可以写出如下代码
|
||||||
|
|
||||||
|
@ -455,7 +455,6 @@ func combinationSum(_ candidates: [Int], _ target: Int) -> [[Int]] {
|
|||||||
var path = [Int]()
|
var path = [Int]()
|
||||||
func backtracking(sum: Int, startIndex: Int) {
|
func backtracking(sum: Int, startIndex: Int) {
|
||||||
// 终止条件
|
// 终止条件
|
||||||
if sum > target { return }
|
|
||||||
if sum == target {
|
if sum == target {
|
||||||
result.append(path)
|
result.append(path)
|
||||||
return
|
return
|
||||||
@ -464,8 +463,11 @@ func combinationSum(_ candidates: [Int], _ target: Int) -> [[Int]] {
|
|||||||
let end = candidates.count
|
let end = candidates.count
|
||||||
guard startIndex < end else { return }
|
guard startIndex < end else { return }
|
||||||
for i in startIndex ..< end {
|
for i in startIndex ..< end {
|
||||||
|
let sum = sum + candidates[i] // 使用局部变量隐藏回溯
|
||||||
|
if sum > target { continue } // 剪枝
|
||||||
|
|
||||||
path.append(candidates[i]) // 处理
|
path.append(candidates[i]) // 处理
|
||||||
backtracking(sum: sum + candidates[i], startIndex: i) // sum这里用新变量完成回溯,i不用+1以重复访问
|
backtracking(sum: sum, startIndex: i) // i不用+1以重复访问
|
||||||
path.removeLast() // 回溯
|
path.removeLast() // 回溯
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -627,7 +627,7 @@ int** combine(int n, int k, int* returnSize, int** returnColumnSizes){
|
|||||||
func combine(_ n: Int, _ k: Int) -> [[Int]] {
|
func combine(_ n: Int, _ k: Int) -> [[Int]] {
|
||||||
var path = [Int]()
|
var path = [Int]()
|
||||||
var result = [[Int]]()
|
var result = [[Int]]()
|
||||||
func backtracking(_ n: Int, _ k: Int, _ startIndex: Int) {
|
func backtracking(start: Int) {
|
||||||
// 结束条件,并收集结果
|
// 结束条件,并收集结果
|
||||||
if path.count == k {
|
if path.count == k {
|
||||||
result.append(path)
|
result.append(path)
|
||||||
@ -638,15 +638,15 @@ func combine(_ n: Int, _ k: Int) -> [[Int]] {
|
|||||||
// let end = n
|
// let end = n
|
||||||
// 剪枝优化
|
// 剪枝优化
|
||||||
let end = n - (k - path.count) + 1
|
let end = n - (k - path.count) + 1
|
||||||
guard startIndex <= end else { return }
|
guard start <= end else { return }
|
||||||
for i in startIndex ... end {
|
for i in start ... end {
|
||||||
path.append(i) // 处理结点
|
path.append(i) // 处理结点
|
||||||
backtracking(n, k, i + 1) // 递归
|
backtracking(start: i + 1) // 递归
|
||||||
path.removeLast() // 回溯
|
path.removeLast() // 回溯
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
backtracking(n, k, 1)
|
backtracking(start: 1)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -300,7 +300,7 @@ Swift:
|
|||||||
func combine(_ n: Int, _ k: Int) -> [[Int]] {
|
func combine(_ n: Int, _ k: Int) -> [[Int]] {
|
||||||
var path = [Int]()
|
var path = [Int]()
|
||||||
var result = [[Int]]()
|
var result = [[Int]]()
|
||||||
func backtracking(_ n: Int, _ k: Int, _ startIndex: Int) {
|
func backtracking(start: Int) {
|
||||||
// 结束条件,并收集结果
|
// 结束条件,并收集结果
|
||||||
if path.count == k {
|
if path.count == k {
|
||||||
result.append(path)
|
result.append(path)
|
||||||
@ -311,15 +311,15 @@ func combine(_ n: Int, _ k: Int) -> [[Int]] {
|
|||||||
// let end = n
|
// let end = n
|
||||||
// 剪枝优化
|
// 剪枝优化
|
||||||
let end = n - (k - path.count) + 1
|
let end = n - (k - path.count) + 1
|
||||||
guard startIndex <= end else { return }
|
guard start <= end else { return }
|
||||||
for i in startIndex ... end {
|
for i in start ... end {
|
||||||
path.append(i) // 处理结点
|
path.append(i) // 处理结点
|
||||||
backtracking(n, k, i + 1) // 递归
|
backtracking(start: i + 1) // 递归
|
||||||
path.removeLast() // 回溯
|
path.removeLast() // 回溯
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
backtracking(n, k, 1)
|
backtracking(start: 1)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
* 107.二叉树的层次遍历II
|
* 107.二叉树的层次遍历II
|
||||||
* 199.二叉树的右视图
|
* 199.二叉树的右视图
|
||||||
* 637.二叉树的层平均值
|
* 637.二叉树的层平均值
|
||||||
* 429.N叉树的前序遍历
|
* 429.N叉树的层序遍历
|
||||||
* 515.在每个树行中找最大值
|
* 515.在每个树行中找最大值
|
||||||
* 116.填充每个节点的下一个右侧节点指针
|
* 116.填充每个节点的下一个右侧节点指针
|
||||||
* 117.填充每个节点的下一个右侧节点指针II
|
* 117.填充每个节点的下一个右侧节点指针II
|
||||||
|
@ -48,7 +48,7 @@ int getdepth(treenode* node)
|
|||||||
|
|
||||||
代码如下:
|
代码如下:
|
||||||
```CPP
|
```CPP
|
||||||
if (node == null) return 0;
|
if (node == NULL) return 0;
|
||||||
```
|
```
|
||||||
|
|
||||||
3. 确定单层递归的逻辑:先求它的左子树的深度,再求的右子树的深度,最后取左右深度最大的数值 再+1 (加1是因为算上当前中间节点)就是目前节点为根节点的树的深度。
|
3. 确定单层递归的逻辑:先求它的左子树的深度,再求的右子树的深度,最后取左右深度最大的数值 再+1 (加1是因为算上当前中间节点)就是目前节点为根节点的树的深度。
|
||||||
@ -68,7 +68,7 @@ return depth;
|
|||||||
class solution {
|
class solution {
|
||||||
public:
|
public:
|
||||||
int getdepth(treenode* node) {
|
int getdepth(treenode* node) {
|
||||||
if (node == null) return 0;
|
if (node == NULL) return 0;
|
||||||
int leftdepth = getdepth(node->left); // 左
|
int leftdepth = getdepth(node->left); // 左
|
||||||
int rightdepth = getdepth(node->right); // 右
|
int rightdepth = getdepth(node->right); // 右
|
||||||
int depth = 1 + max(leftdepth, rightdepth); // 中
|
int depth = 1 + max(leftdepth, rightdepth); // 中
|
||||||
@ -104,7 +104,7 @@ public:
|
|||||||
void getdepth(treenode* node, int depth) {
|
void getdepth(treenode* node, int depth) {
|
||||||
result = depth > result ? depth : result; // 中
|
result = depth > result ? depth : result; // 中
|
||||||
|
|
||||||
if (node->left == null && node->right == null) return ;
|
if (node->left == NULL && node->right == NULL) return ;
|
||||||
|
|
||||||
if (node->left) { // 左
|
if (node->left) { // 左
|
||||||
depth++; // 深度+1
|
depth++; // 深度+1
|
||||||
@ -137,7 +137,7 @@ public:
|
|||||||
int result;
|
int result;
|
||||||
void getdepth(treenode* node, int depth) {
|
void getdepth(treenode* node, int depth) {
|
||||||
result = depth > result ? depth : result; // 中
|
result = depth > result ? depth : result; // 中
|
||||||
if (node->left == null && node->right == null) return ;
|
if (node->left == NULL && node->right == NULL) return ;
|
||||||
if (node->left) { // 左
|
if (node->left) { // 左
|
||||||
getdepth(node->left, depth + 1);
|
getdepth(node->left, depth + 1);
|
||||||
}
|
}
|
||||||
@ -173,7 +173,7 @@ c++代码如下:
|
|||||||
class solution {
|
class solution {
|
||||||
public:
|
public:
|
||||||
int maxdepth(treenode* root) {
|
int maxdepth(treenode* root) {
|
||||||
if (root == null) return 0;
|
if (root == NULL) return 0;
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
queue<treenode*> que;
|
queue<treenode*> que;
|
||||||
que.push(root);
|
que.push(root);
|
||||||
@ -238,7 +238,7 @@ class solution {
|
|||||||
public:
|
public:
|
||||||
int maxdepth(node* root) {
|
int maxdepth(node* root) {
|
||||||
queue<node*> que;
|
queue<node*> que;
|
||||||
if (root != null) que.push(root);
|
if (root != NULL) que.push(root);
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
while (!que.empty()) {
|
while (!que.empty()) {
|
||||||
int size = que.size();
|
int size = que.size();
|
||||||
|
@ -575,12 +575,9 @@ func partition(_ s: String) -> [[String]] {
|
|||||||
|
|
||||||
for i in startIndex ..< s.count {
|
for i in startIndex ..< s.count {
|
||||||
// 回文则收集,否则跳过
|
// 回文则收集,否则跳过
|
||||||
if isPalindrome(start: startIndex, end: i) {
|
guard isPalindrome(start: startIndex, end: i) else { continue }
|
||||||
let substring = String(s[startIndex ... i])
|
let substring = String(s[startIndex ... i])
|
||||||
path.append(substring)
|
path.append(substring) // 处理
|
||||||
} else {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
backtracking(startIndex: i + 1) // 寻找下一个起始位置的子串
|
backtracking(startIndex: i + 1) // 寻找下一个起始位置的子串
|
||||||
if !path.isEmpty { path.removeLast() } // 回溯
|
if !path.isEmpty { path.removeLast() } // 回溯
|
||||||
}
|
}
|
||||||
|
@ -220,7 +220,7 @@ public:
|
|||||||
|
|
||||||
但因为分割子串的特殊性,遍历背包放在外循环,将遍历物品放在内循环更方便一些。
|
但因为分割子串的特殊性,遍历背包放在外循环,将遍历物品放在内循环更方便一些。
|
||||||
|
|
||||||
本题其实递推公式都不是重点,遍历顺序才是重点,如果我直接把代码贴出来,估计同学们也会想两个for循环的顺序理所当然就是这样,甚至都不会想为什么遍历背包的for循环为什么在外层。
|
本题其实递推公式都不是重点,遍历顺序才是重点,如果我直接把代码贴出来,估计同学们也会想两个for循环的顺序理所当然就是这样,甚至都不会想为什么遍历背包的for循环在外层。
|
||||||
|
|
||||||
不分析透彻不是Carl的风格啊,哈哈
|
不分析透彻不是Carl的风格啊,哈哈
|
||||||
|
|
||||||
|
@ -462,7 +462,7 @@ int** combinationSum3(int k, int n, int* returnSize, int** returnColumnSizes){
|
|||||||
func combinationSum3(_ count: Int, _ targetSum: Int) -> [[Int]] {
|
func combinationSum3(_ count: Int, _ targetSum: Int) -> [[Int]] {
|
||||||
var result = [[Int]]()
|
var result = [[Int]]()
|
||||||
var path = [Int]()
|
var path = [Int]()
|
||||||
func backtracking(sum: Int, startIndex: Int) {
|
func backtracking(sum: Int, start: Int) {
|
||||||
// 剪枝
|
// 剪枝
|
||||||
if sum > targetSum { return }
|
if sum > targetSum { return }
|
||||||
// 终止条件
|
// 终止条件
|
||||||
@ -474,16 +474,16 @@ func combinationSum3(_ count: Int, _ targetSum: Int) -> [[Int]] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 单层逻辑
|
// 单层逻辑
|
||||||
let endIndex = 9
|
let end = 9
|
||||||
guard startIndex <= endIndex else { return }
|
guard start <= end else { return }
|
||||||
for i in startIndex ... endIndex {
|
for i in start ... end {
|
||||||
path.append(i) // 处理
|
path.append(i) // 处理
|
||||||
backtracking(sum: sum + i, startIndex: i + 1)
|
backtracking(sum: sum + i, start: i + 1)
|
||||||
path.removeLast() // 回溯
|
path.removeLast() // 回溯
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
backtracking(sum: 0, startIndex: 1)
|
backtracking(sum: 0, start: 1)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
1. 确定dp数组(dp table)以及下标的含义
|
1. 确定dp数组(dp table)以及下标的含义
|
||||||
|
|
||||||
**dp[i]:和为i的完全平方数的最少数量为dp[i]**
|
**dp[j]:和为j的完全平方数的最少数量为dp[j]**
|
||||||
|
|
||||||
2. 确定递推公式
|
2. 确定递推公式
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ dp[0]表示 和为0的完全平方数的最小数量,那么dp[0]一定是0。
|
|||||||
|
|
||||||
非0下标的dp[j]应该是多少呢?
|
非0下标的dp[j]应该是多少呢?
|
||||||
|
|
||||||
从递归公式dp[j] = min(dp[j - i * i] + 1, dp[j]);中可以看出每次dp[j]都要选最小的,**所以非0下标的dp[i]一定要初始为最大值,这样dp[j]在递推的时候才不会被初始值覆盖**。
|
从递归公式dp[j] = min(dp[j - i * i] + 1, dp[j]);中可以看出每次dp[j]都要选最小的,**所以非0下标的dp[j]一定要初始为最大值,这样dp[j]在递推的时候才不会被初始值覆盖**。
|
||||||
|
|
||||||
4. 确定遍历顺序
|
4. 确定遍历顺序
|
||||||
|
|
||||||
@ -70,9 +70,9 @@ dp[0]表示 和为0的完全平方数的最小数量,那么dp[0]一定是0。
|
|||||||
|
|
||||||
在[动态规划:322. 零钱兑换](https://programmercarl.com/0322.零钱兑换.html)中我们就深入探讨了这个问题,本题也是一样的,是求最小数!
|
在[动态规划:322. 零钱兑换](https://programmercarl.com/0322.零钱兑换.html)中我们就深入探讨了这个问题,本题也是一样的,是求最小数!
|
||||||
|
|
||||||
**所以本题外层for遍历背包,里层for遍历物品,还是外层for遍历物品,内层for遍历背包,都是可以的!**
|
**所以本题外层for遍历背包,内层for遍历物品,还是外层for遍历物品,内层for遍历背包,都是可以的!**
|
||||||
|
|
||||||
我这里先给出外层遍历背包,里层遍历物品的代码:
|
我这里先给出外层遍历背包,内层遍历物品的代码:
|
||||||
|
|
||||||
```CPP
|
```CPP
|
||||||
vector<int> dp(n + 1, INT_MAX);
|
vector<int> dp(n + 1, INT_MAX);
|
||||||
|
@ -81,7 +81,7 @@ dp[0] = 0;
|
|||||||
|
|
||||||
4. 确定遍历顺序
|
4. 确定遍历顺序
|
||||||
|
|
||||||
本题求钱币最小个数,**那么钱币有顺序和没有顺序都可以,都不影响钱币的最小个数。**。
|
本题求钱币最小个数,**那么钱币有顺序和没有顺序都可以,都不影响钱币的最小个数**。
|
||||||
|
|
||||||
所以本题并不强调集合是组合还是排列。
|
所以本题并不强调集合是组合还是排列。
|
||||||
|
|
||||||
@ -170,7 +170,7 @@ public:
|
|||||||
|
|
||||||
这也是我为什么要先讲518.零钱兑换II 然后再讲本题即:322.零钱兑换,这是Carl的良苦用心那。
|
这也是我为什么要先讲518.零钱兑换II 然后再讲本题即:322.零钱兑换,这是Carl的良苦用心那。
|
||||||
|
|
||||||
相信大家看完之后,对背包问题中的遍历顺序又了更深的理解了。
|
相信大家看完之后,对背包问题中的遍历顺序有更深的理解了。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -261,6 +261,7 @@ func wiggleMaxLength(nums []int) int {
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Javascript
|
### Javascript
|
||||||
|
**贪心**
|
||||||
```Javascript
|
```Javascript
|
||||||
var wiggleMaxLength = function(nums) {
|
var wiggleMaxLength = function(nums) {
|
||||||
if(nums.length <= 1) return nums.length
|
if(nums.length <= 1) return nums.length
|
||||||
@ -277,6 +278,25 @@ var wiggleMaxLength = function(nums) {
|
|||||||
return result
|
return result
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
**动态规划**
|
||||||
|
```Javascript
|
||||||
|
var wiggleMaxLength = function(nums) {
|
||||||
|
if (nums.length === 1) return 1;
|
||||||
|
// 考虑前i个数,当第i个值作为峰谷时的情况(则第i-1是峰顶)
|
||||||
|
let down = 1;
|
||||||
|
// 考虑前i个数,当第i个值作为峰顶时的情况(则第i-1是峰谷)
|
||||||
|
let up = 1;
|
||||||
|
for (let i = 1; i < nums.length; i++) {
|
||||||
|
if (nums[i] < nums[i - 1]) {
|
||||||
|
down = Math.max(up + 1, down);
|
||||||
|
}
|
||||||
|
if (nums[i] > nums[i - 1]) {
|
||||||
|
up = Math.max(down + 1, up)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Math.max(down, up);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||||
|
@ -706,6 +706,9 @@ func (this *MyLinkedList) AddAtIndex(index int, val int) {
|
|||||||
head = head.Next
|
head = head.Next
|
||||||
index--
|
index--
|
||||||
}
|
}
|
||||||
|
if index > 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
node := &Node{
|
node := &Node{
|
||||||
Val: val,
|
Val: val,
|
||||||
//node.Next = MyLinkedList[index]
|
//node.Next = MyLinkedList[index]
|
||||||
|
@ -152,8 +152,7 @@ public:
|
|||||||
vector<int> dailyTemperatures(vector<int>& T) {
|
vector<int> dailyTemperatures(vector<int>& T) {
|
||||||
stack<int> st; // 递减栈
|
stack<int> st; // 递减栈
|
||||||
vector<int> result(T.size(), 0);
|
vector<int> result(T.size(), 0);
|
||||||
st.push(0);
|
for (int i = 0; i < T.size(); i++) {
|
||||||
for (int i = 1; i < T.size(); i++) {
|
|
||||||
while (!st.empty() && T[i] > T[st.top()]) { // 注意栈不能为空
|
while (!st.empty() && T[i] > T[st.top()]) { // 注意栈不能为空
|
||||||
result[st.top()] = i - st.top();
|
result[st.top()] = i - st.top();
|
||||||
st.pop();
|
st.pop();
|
||||||
|
@ -90,7 +90,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
如下为精简之后的递归代码:(257. 二叉树的所有路径)
|
如下为精简之后的递归代码:(257. 二叉树的所有路径)
|
||||||
```
|
```CPP
|
||||||
class Solution {
|
class Solution {
|
||||||
private:
|
private:
|
||||||
void traversal(TreeNode* cur, string path, vector<string>& result) {
|
void traversal(TreeNode* cur, string path, vector<string>& result) {
|
||||||
@ -131,8 +131,7 @@ traversal(cur->left, path, result); // 左
|
|||||||
|
|
||||||
即:
|
即:
|
||||||
|
|
||||||
```
|
``` CPP
|
||||||
|
|
||||||
if (cur->left) {
|
if (cur->left) {
|
||||||
path += "->";
|
path += "->";
|
||||||
traversal(cur->left, path, result); // 左
|
traversal(cur->left, path, result); // 左
|
||||||
|
@ -85,7 +85,7 @@ public:
|
|||||||
|
|
||||||
关键看遍历顺序。
|
关键看遍历顺序。
|
||||||
|
|
||||||
本题求钱币最小个数,**那么钱币有顺序和没有顺序都可以,都不影响钱币的最小个数。**。
|
本题求钱币最小个数,**那么钱币有顺序和没有顺序都可以,都不影响钱币的最小个数**。
|
||||||
|
|
||||||
所以本题并不强调集合是组合还是排列。
|
所以本题并不强调集合是组合还是排列。
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
## 周一
|
## 周一
|
||||||
|
|
||||||
[动态规划:开始打家劫舍!](https://programmercarl.com/0198.打家劫舍.html)中就是给一个数组相邻之间不能连着偷,如果偷才能得到最大金钱。
|
[动态规划:开始打家劫舍!](https://programmercarl.com/0198.打家劫舍.html)中就是给一个数组相邻之间不能连着偷,如何偷才能得到最大金钱。
|
||||||
|
|
||||||
1. 确定dp数组含义
|
1. 确定dp数组含义
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ dp[1] = max(nums[0], nums[1]);
|
|||||||
|
|
||||||
## 周三
|
## 周三
|
||||||
|
|
||||||
[动态规划:还要打家劫舍!](https://programmercarl.com/0337.打家劫舍III.html)这次是在一颗二叉树上打家劫舍了,条件还是一样的,相临的不能偷。
|
[动态规划:还要打家劫舍!](https://programmercarl.com/0337.打家劫舍III.html)这次是在一棵二叉树上打家劫舍了,条件还是一样的,相临的不能偷。
|
||||||
|
|
||||||
这道题目是树形DP的入门题目,其实树形DP其实就是在树上进行递推公式的推导,没有什么神秘的。
|
这道题目是树形DP的入门题目,其实树形DP其实就是在树上进行递推公式的推导,没有什么神秘的。
|
||||||
|
|
||||||
@ -191,12 +191,12 @@ return {val2, val1};
|
|||||||
|
|
||||||
## 周四
|
## 周四
|
||||||
|
|
||||||
[动态规划:买卖股票的最佳时机](https://programmercarl.com/0121.买卖股票的最佳时机.html) 一段时间,只能买买一次,问最大收益。
|
[动态规划:买卖股票的最佳时机](https://programmercarl.com/0121.买卖股票的最佳时机.html) 一段时间,只能买卖一次,问最大收益。
|
||||||
|
|
||||||
这里我给出了三中解法:
|
这里我给出了三种解法:
|
||||||
|
|
||||||
暴力解法代码:
|
暴力解法代码:
|
||||||
```
|
```CPP
|
||||||
class Solution {
|
class Solution {
|
||||||
public:
|
public:
|
||||||
int maxProfit(vector<int>& prices) {
|
int maxProfit(vector<int>& prices) {
|
||||||
|
@ -331,7 +331,7 @@ used数组可是全局变量,每层与每层之间公用一个used数组,所
|
|||||||
|
|
||||||
在[回溯算法:N皇后问题](https://programmercarl.com/0051.N皇后.html)中终于迎来了传说中的N皇后。
|
在[回溯算法:N皇后问题](https://programmercarl.com/0051.N皇后.html)中终于迎来了传说中的N皇后。
|
||||||
|
|
||||||
下面我用一个3 * 3 的棋牌,将搜索过程抽象为一颗树,如图:
|
下面我用一个3 * 3 的棋盘,将搜索过程抽象为一颗树,如图:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@ -437,20 +437,5 @@ N皇后问题分析:
|
|||||||
**回溯算法系列正式结束,新的系列终将开始,录友们准备开启新的征程!**
|
**回溯算法系列正式结束,新的系列终将开始,录友们准备开启新的征程!**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 其他语言版本
|
|
||||||
|
|
||||||
|
|
||||||
Java:
|
|
||||||
|
|
||||||
|
|
||||||
Python:
|
|
||||||
|
|
||||||
|
|
||||||
Go:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
# 动态规划:关于多重背包,你该了解这些!
|
# 动态规划:关于多重背包,你该了解这些!
|
||||||
|
|
||||||
之前我们已经体统的讲解了01背包和完全背包,如果没有看过的录友,建议先把如下三篇文章仔细阅读一波。
|
之前我们已经系统的讲解了01背包和完全背包,如果没有看过的录友,建议先把如下三篇文章仔细阅读一波。
|
||||||
|
|
||||||
* [动态规划:关于01背包问题,你该了解这些!](https://programmercarl.com/背包理论基础01背包-1.html)
|
* [动态规划:关于01背包问题,你该了解这些!](https://programmercarl.com/背包理论基础01背包-1.html)
|
||||||
* [动态规划:关于01背包问题,你该了解这些!(滚动数组)](https://programmercarl.com/背包理论基础01背包-2.html)
|
* [动态规划:关于01背包问题,你该了解这些!(滚动数组)](https://programmercarl.com/背包理论基础01背包-2.html)
|
||||||
|
@ -177,8 +177,8 @@ int main() {
|
|||||||
Java:
|
Java:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
//先遍历物品,再遍历背包
|
//先遍历物品,再遍历背包
|
||||||
private static void testCompletePack(){
|
private static void testCompletePack(){
|
||||||
int[] weight = {1, 3, 4};
|
int[] weight = {1, 3, 4};
|
||||||
int[] value = {15, 20, 30};
|
int[] value = {15, 20, 30};
|
||||||
int bagWeight = 4;
|
int bagWeight = 4;
|
||||||
@ -193,10 +193,10 @@ Java:
|
|||||||
for (int maxValue : dp){
|
for (int maxValue : dp){
|
||||||
System.out.println(maxValue + " ");
|
System.out.println(maxValue + " ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//先遍历背包,再遍历物品
|
//先遍历背包,再遍历物品
|
||||||
private static void testCompletePackAnotherWay(){
|
private static void testCompletePackAnotherWay(){
|
||||||
int[] weight = {1, 3, 4};
|
int[] weight = {1, 3, 4};
|
||||||
int[] value = {15, 20, 30};
|
int[] value = {15, 20, 30};
|
||||||
int bagWeight = 4;
|
int bagWeight = 4;
|
||||||
@ -211,7 +211,7 @@ Java:
|
|||||||
for (int maxValue : dp){
|
for (int maxValue : dp){
|
||||||
System.out.println(maxValue + " ");
|
System.out.println(maxValue + " ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user