Merge branch 'youngyangyang04:master' into remote

This commit is contained in:
Arthur Pan
2022-01-02 14:21:20 +00:00
committed by GitHub
10 changed files with 150 additions and 33 deletions

View File

@ -571,7 +571,7 @@
也欢迎与我交流,备注:「个人简单介绍」 + 交流,围观朋友圈,做点赞之交(备注没有自我介绍不通过哦) 也欢迎与我交流,备注:「个人简单介绍」 + 交流,围观朋友圈,做点赞之交(备注没有自我介绍不通过哦)
<a name="微信"></a> <a name="微信"></a>
<div align="center"><img src="https://code-thinking-1253855093.file.myqcloud.com/pics/WechatIMG82.jpeg" data-img="1" width="200" height="200"></img></div> <div align="center"><img src="https://code-thinking-1253855093.file.myqcloud.com/pics/20211230153955.png" data-img="1" width="200" height="200"></img></div>
# 公众号 # 公众号

View File

@ -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();

View File

@ -71,14 +71,14 @@ vector<vector<int>> dp(prices.size(), vector<int>(2 * k + 1, 0));
* 操作一第i天买入股票了那么dp[i][1] = dp[i - 1][0] - prices[i] * 操作一第i天买入股票了那么dp[i][1] = dp[i - 1][0] - prices[i]
* 操作二第i天没有操作而是沿用前一天买入的状态dp[i][1] = dp[i - 1][1] * 操作二第i天没有操作而是沿用前一天买入的状态dp[i][1] = dp[i - 1][1]
选最大的,所以 dp[i][1] = max(dp[i - 1][0] - prices[i], dp[i - 1][0]); 选最大的,所以 dp[i][1] = max(dp[i - 1][0] - prices[i], dp[i - 1][1]);
同理dp[i][2]也有两个操作: 同理dp[i][2]也有两个操作:
* 操作一第i天卖出股票了那么dp[i][2] = dp[i - 1][1] + prices[i] * 操作一第i天卖出股票了那么dp[i][2] = dp[i - 1][1] + prices[i]
* 操作二第i天没有操作沿用前一天卖出股票的状态dp[i][2] = dp[i - 1][2] * 操作二第i天没有操作沿用前一天卖出股票的状态dp[i][2] = dp[i - 1][2]
所以dp[i][2] = max(dp[i - 1][i] + prices[i], dp[i][2]) 所以dp[i][2] = max(dp[i - 1][1] + prices[i], dp[i - 1][2])
同理可以类比剩下的状态,代码如下: 同理可以类比剩下的状态,代码如下:

View File

@ -64,6 +64,8 @@
那么问题来了定义一个大小为k的大顶堆在每次移动更新大顶堆的时候每次弹出都把最大的元素弹出去了那么怎么保留下来前K个高频元素呢。 那么问题来了定义一个大小为k的大顶堆在每次移动更新大顶堆的时候每次弹出都把最大的元素弹出去了那么怎么保留下来前K个高频元素呢。
而且使用大顶堆就要把所有元素都进行排序那能不能只排序k个元素呢
**所以我们要用小顶堆因为要统计最大前k个元素只有小顶堆每次将最小的元素弹出最后小顶堆里积累的才是前k个最大元素。** **所以我们要用小顶堆因为要统计最大前k个元素只有小顶堆每次将最小的元素弹出最后小顶堆里积累的才是前k个最大元素。**
寻找前k个最大元素流程如图所示图中的频率只有三个所以正好构成一个大小为3的小顶堆如果频率更多一些则用这个小顶堆进行扫描 寻找前k个最大元素流程如图所示图中的频率只有三个所以正好构成一个大小为3的小顶堆如果频率更多一些则用这个小顶堆进行扫描

View File

@ -34,7 +34,7 @@
* 解释S 会变成 “c”但 T 仍然是 “b”。 * 解释S 会变成 “c”但 T 仍然是 “b”。
# 思路 ## 思路
本文将给出 空间复杂度$O(n)$的栈模拟方法 以及空间复杂度是$O(1)$的双指针方法。 本文将给出 空间复杂度$O(n)$的栈模拟方法 以及空间复杂度是$O(1)$的双指针方法。
@ -155,9 +155,9 @@ public:
* 空间复杂度:$O(1)$ * 空间复杂度:$O(1)$
# 其他语言版本 ## 其他语言版本
Java ### Java
```java ```java
// 普通方法(使用栈的思路) // 普通方法(使用栈的思路)
@ -185,9 +185,8 @@ class Solution {
} }
``` ```
Python
python3 ### python
```python ```python
class Solution: class Solution:
@ -207,8 +206,7 @@ class Solution:
pass pass
``` ```
### Go
Go
```go ```go
@ -230,7 +228,7 @@ func backspaceCompare(s string, t string) bool {
``` ```
JavaScript ### JavaScript
```javascript ```javascript
// 双栈 // 双栈
var backspaceCompare = function(s, t) { var backspaceCompare = function(s, t) {

View File

@ -34,7 +34,7 @@
* 输出true * 输出true
* 解释:长按名字中的字符并不是必要的。 * 解释:长按名字中的字符并不是必要的。
# 思路 ## 思路
这道题目一看以为是哈希,仔细一看不行,要有顺序。 这道题目一看以为是哈希,仔细一看不行,要有顺序。
@ -94,9 +94,9 @@ public:
空间复杂度:$O(1)$ 空间复杂度:$O(1)$
# 其他语言版本 ## 其他语言版本
Java ### Java
```java ```java
class Solution { class Solution {
public boolean isLongPressedName(String name, String typed) { public boolean isLongPressedName(String name, String typed) {
@ -127,7 +127,7 @@ class Solution {
} }
} }
``` ```
Python ### Python
```python ```python
class Solution: class Solution:
def isLongPressedName(self, name: str, typed: str) -> bool: def isLongPressedName(self, name: str, typed: str) -> bool:
@ -154,7 +154,7 @@ class Solution:
return True return True
``` ```
Go ### Go
```go ```go
@ -179,7 +179,7 @@ func isLongPressedName(name string, typed string) bool {
} }
``` ```
JavaScript ### JavaScript
```javascript ```javascript
var isLongPressedName = function(name, typed) { var isLongPressedName = function(name, typed) {
let i = 0, j = 0; let i = 0, j = 0;

View File

@ -38,7 +38,7 @@
* 输出2 * 输出2
* 解释s 可以分割为 "RL"、"RRRLLRLL" ,每个子字符串中都包含相同数量的 'L' 和 'R' 。 * 解释s 可以分割为 "RL"、"RRRLLRLL" ,每个子字符串中都包含相同数量的 'L' 和 'R' 。
# 思路 ## 思路
这道题目看起来好像很复杂,其实是非常简单的贪心,关于贪心,我在这里[关于贪心算法,你该了解这些!](https://programmercarl.com/贪心算法理论基础.html)有详细的讲解。 这道题目看起来好像很复杂,其实是非常简单的贪心,关于贪心,我在这里[关于贪心算法,你该了解这些!](https://programmercarl.com/贪心算法理论基础.html)有详细的讲解。
@ -71,7 +71,7 @@ public:
}; };
``` ```
# 拓展 ## 拓展
一些同学可能想,你这个推理不靠谱,都没有数学证明。怎么就能说是合理的呢,怎么就能说明 局部最优可以推出全局最优呢? 一些同学可能想,你这个推理不靠谱,都没有数学证明。怎么就能说是合理的呢,怎么就能说明 局部最优可以推出全局最优呢?
@ -86,9 +86,9 @@ public:
# 其他语言版本 ## 其他语言版本
## Java ### Java
```java ```java
class Solution { class Solution {
@ -105,17 +105,17 @@ class Solution {
} }
``` ```
## Python ### Python
```python ```python
``` ```
## Go ### Go
```go ```go
``` ```
## JavaScript ### JavaScript
```js ```js
var balancedStringSplit = function(s) { var balancedStringSplit = function(s) {

View File

@ -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); // 左

View File

@ -454,6 +454,79 @@ var postorderTraversal = function(root, res = []) {
}; };
``` ```
Swift:
> 迭代法前序遍历
```swift
func preorderTraversal(_ root: TreeNode?) -> [Int] {
var res = [Int]()
if root == nil {
return res
}
var stack = [TreeNode]()
stack.append(root!)
while !stack.isEmpty {
let node = stack.popLast()!
res.append(node.val)
if node.right != nil {
stack.append(node.right!)
}
if node.left != nil {
stack.append(node.left!)
}
}
return res
}
```
> 迭代法中序遍历
```swift
func inorderTraversal(_ root: TreeNode?) -> [Int] {
var res = [Int]()
if root == nil {
return res
}
var stack = [TreeNode]()
var cur: TreeNode? = root
while cur != nil || !stack.isEmpty {
if cur != nil {
stack.append(cur!)
cur = cur!.left
} else {
cur = stack.popLast()
res.append(cur!.val)
cur = cur!.right
}
}
return res
}
```
> 迭代法后序遍历
```swift
func postorderTraversal(_ root: TreeNode?) -> [Int] {
var res = [Int]()
if root == nil {
return res
}
var stack = [TreeNode]()
stack.append(root!)
// res 存储 中 -> 右 -> 左
while !stack.isEmpty {
let node = stack.popLast()!
res.append(node.val)
if node.left != nil {
stack.append(node.left!)
}
if node.right != nil {
stack.append(node.right!)
}
}
// res 翻转
res.reverse()
return res
}
```
----------------------- -----------------------
<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>

View File

@ -147,6 +147,51 @@ int main() {
Java Java
```Java
public void testMultiPack1(){
// 版本一改变物品数量为01背包格式
List<Integer> weight = new ArrayList<>(Arrays.asList(1, 3, 4));
List<Integer> value = new ArrayList<>(Arrays.asList(15, 20, 30));
List<Integer> nums = new ArrayList<>(Arrays.asList(2, 3, 2));
int bagWeight = 10;
for (int i = 0; i < nums.size(); i++) {
while (nums.get(i) > 1) { // 把物品展开为i
weight.add(weight.get(i));
value.add(value.get(i));
nums.set(i, nums.get(i) - 1);
}
}
int[] dp = new int[bagWeight + 1];
for(int i = 0; i < weight.size(); i++) { // 遍历物品
for(int j = bagWeight; j >= weight.get(i); j--) { // 遍历背包容量
dp[j] = Math.max(dp[j], dp[j - weight.get(i)] + value.get(i));
}
System.out.println(Arrays.toString(dp));
}
}
public void testMultiPack2(){
// 版本二:改变遍历个数
int[] weight = new int[] {1, 3, 4};
int[] value = new int[] {15, 20, 30};
int[] nums = new int[] {2, 3, 2};
int bagWeight = 10;
int[] dp = new int[bagWeight + 1];
for(int i = 0; i < weight.length; i++) { // 遍历物品
for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
// 以上为01背包然后加一个遍历个数
for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) { // 遍历个数
dp[j] = Math.max(dp[j], dp[j - k * weight[i]] + k * value[i]);
}
System.out.println(Arrays.toString(dp));
}
}
}
```
Python Python
```python ```python