diff --git a/README.md b/README.md index dd70d8cb..5fe165a7 100644 --- a/README.md +++ b/README.md @@ -396,7 +396,7 @@ * [图论:深度优先搜索理论基础](./problems/图论深搜理论基础.md) * [图论:797.所有可能的路径](./problems/0797.所有可能的路径.md) -* [图论:广度优先搜索理论基础](./problems/图论广索理论基础.md) +* [图论:广度优先搜索理论基础](./problems/图论广搜理论基础.md) * [图论:200.岛屿数量.深搜版](./problems/0200.岛屿数量.深搜版.md) * [图论:200.岛屿数量.广搜版](./problems/0200.岛屿数量.广搜版.md) * [图论:695.岛屿的最大面积](./problems/0695.岛屿的最大面积.md) diff --git a/problems/0001.两数之和.md b/problems/0001.两数之和.md index ca62e3ed..e3fb0fb5 100644 --- a/problems/0001.两数之和.md +++ b/problems/0001.两数之和.md @@ -5,7 +5,7 @@
参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!
-## 1. 两数之和 +# 1. 两数之和 [力扣题目链接](https://leetcode.cn/problems/two-sum/) @@ -21,11 +21,13 @@ 所以返回 [0, 1] +## 算法公开课 + +**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[梦开始的地方,Leetcode:1.两数之和](https://www.bilibili.com/video/BV1aT41177mK),相信结合视频再看本篇题解,更有助于大家对本题的理解**。 + ## 思路 -建议看一下我录的这期视频:[梦开始的地方,Leetcode:1.两数之和](https://www.bilibili.com/video/BV1aT41177mK),结合本题解来学习,事半功倍。 - 很明显暴力的解法是两层for循环查找,时间复杂度是O(n^2)。 建议大家做这道题目之前,先做一下这两道 @@ -128,8 +130,8 @@ public: ## 其他语言版本 +### Java: -Java: ```java public int[] twoSum(int[] nums, int target) { int[] res = new int[2]; @@ -150,8 +152,9 @@ public int[] twoSum(int[] nums, int target) { } ``` -Python: +### Python: (版本一) 使用字典 + ```python class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: @@ -211,7 +214,7 @@ class Solution: return [i,j] ``` -Go: +### Go: ```go // 暴力解法 @@ -242,7 +245,7 @@ func twoSum(nums []int, target int) []int { } ``` -Rust +### Rust: ```rust use std::collections::HashMap; @@ -263,9 +266,7 @@ impl Solution { } } ``` -Rust - -``` +```rust use std::collections::HashMap; impl Solution { @@ -284,7 +285,7 @@ impl Solution { } ``` -Javascript +### Javascript: ```javascript var twoSum = function (nums, target) { @@ -299,7 +300,7 @@ var twoSum = function (nums, target) { }; ``` -TypeScript: +### TypeScript: ```typescript function twoSum(nums: number[], target: number): number[] { @@ -317,7 +318,7 @@ function twoSum(nums: number[], target: number): number[] { }; ``` -php +### php: ```php function twoSum(array $nums, int $target): array @@ -337,7 +338,8 @@ function twoSum(array $nums, int $target): array } ``` -Swift: +### Swift: + ```swift func twoSum(_ nums: [Int], _ target: Int) -> [Int] { // 值: 下标 @@ -353,8 +355,8 @@ func twoSum(_ nums: [Int], _ target: Int) -> [Int] { } ``` +### Scala: -Scala: ```scala object Solution { // 导入包 @@ -377,7 +379,8 @@ object Solution { } ``` -C#: +### C#: + ```csharp public class Solution { public int[] TwoSum(int[] nums, int target) { @@ -396,7 +399,8 @@ public class Solution { } ``` -Dart: +### Dart: + ```dart List
+
diff --git a/problems/0017.电话号码的字母组合.md b/problems/0017.电话号码的字母组合.md
index cf5e4520..b3ba1e5e 100644
--- a/problems/0017.电话号码的字母组合.md
+++ b/problems/0017.电话号码的字母组合.md
@@ -21,12 +21,12 @@
说明:尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[还得用回溯算法!| LeetCode:17.电话号码的字母组合](https://www.bilibili.com/video/BV1yV4y1V7Ug),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)::[还得用回溯算法!| LeetCode:17.电话号码的字母组合](https://www.bilibili.com/video/BV1yV4y1V7Ug),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
-# 思路
+## 思路
从示例上来说,输入"23",最直接的想法就是两层for循环遍历了吧,正好把组合的情况都输出了。
@@ -40,7 +40,7 @@
2. 两个字母就两个for循环,三个字符我就三个for循环,以此类推,然后发现代码根本写不出来
3. 输入1 * #按键等等异常情况
-## 数字和字母如何映射
+### 数字和字母如何映射
可以使用map或者定义一个二维数组,例如:string letterMap[10],来做映射,我这里定义一个二维数组,代码如下:
@@ -59,7 +59,7 @@ const string letterMap[10] = {
};
```
-## 回溯法来解决n个for循环的问题
+### 回溯法来解决n个for循环的问题
对于回溯法还不了解的同学看这篇:[关于回溯算法,你该了解这些!](https://programmercarl.com/回溯算法理论基础.html)
@@ -134,9 +134,6 @@ for (int i = 0; i < letters.size(); i++) {
**但是要知道会有这些异常,如果是现场面试中,一定要考虑到!**
-
-## C++代码
-
关键地方都讲完了,按照[关于回溯算法,你该了解这些!](https://programmercarl.com/回溯算法理论基础.html)中的回溯法模板,不难写出如下C++代码:
@@ -233,7 +230,7 @@ public:
所以大家可以按照版本一来写就可以了。
-# 总结
+## 总结
本篇将题目的三个要点一一列出,并重点强调了和前面讲解过的[77. 组合](https://programmercarl.com/0077.组合.html)和[216.组合总和III](https://programmercarl.com/0216.组合总和III.html)的区别,本题是多个集合求组合,所以在回溯的搜索过程中,都有一些细节需要注意的。
@@ -241,10 +238,10 @@ public:
-# 其他语言版本
+## 其他语言版本
-## Java
+### Java
```Java
class Solution {
@@ -286,7 +283,7 @@ class Solution {
}
```
-## Python
+### Python
回溯
```python
class Solution:
@@ -435,7 +432,7 @@ class Solution:
-## Go
+### Go
主要在于递归中传递下一个数字
@@ -470,7 +467,7 @@ func dfs(digits string, start int) {
}
```
-## javaScript
+### JavaScript
```js
var letterCombinations = function(digits) {
@@ -497,7 +494,7 @@ var letterCombinations = function(digits) {
};
```
-## TypeScript
+### TypeScript
```typescript
function letterCombinations(digits: string): string[] {
@@ -531,7 +528,7 @@ function letterCombinations(digits: string): string[] {
};
```
-## Rust
+### Rust
```Rust
const map: [&str; 10] = [
@@ -563,7 +560,7 @@ impl Solution {
}
```
-## C
+### C
```c
char* path;
@@ -625,7 +622,7 @@ char ** letterCombinations(char * digits, int* returnSize){
}
```
-## Swift
+### Swift
```swift
func letterCombinations(_ digits: String) -> [String] {
@@ -666,7 +663,7 @@ func letterCombinations(_ digits: String) -> [String] {
}
```
-## Scala:
+### Scala
```scala
object Solution {
@@ -702,3 +699,4 @@ object Solution {
+
diff --git a/problems/0018.四数之和.md b/problems/0018.四数之和.md
index a4d41d9b..28c20b7a 100644
--- a/problems/0018.四数之和.md
+++ b/problems/0018.四数之和.md
@@ -27,9 +27,11 @@
[-2, 0, 0, 2]
]
-# 思路
+## 算法公开课
-针对本题,我录制了视频讲解:[难在去重和剪枝!| LeetCode:18. 四数之和](https://www.bilibili.com/video/BV1DS4y147US),结合本题解一起看,事半功倍!
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[难在去重和剪枝!| LeetCode:18. 四数之和](https://www.bilibili.com/video/BV1DS4y147US),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+
+## 思路
四数之和,和[15.三数之和](https://programmercarl.com/0015.三数之和.html)是一个思路,都是使用双指针法, 基本解法就是在[15.三数之和](https://programmercarl.com/0015.三数之和.html) 的基础上再套一层for循环。
@@ -141,22 +143,16 @@ if (nums[k] + nums[i] > target && nums[k] + nums[i] >= 0) {
if (nums[k] + nums[i] > target && nums[i] >= 0) {
break;
}
-```
+```
因为只要 nums[k] + nums[i] > target,那么 nums[i] 后面的数都是正数的话,就一定 不符合条件了。
不过这种剪枝 其实有点 小绕,大家能够理解 文章给的完整代码的剪枝 就够了。
-
-
-
-
-
-
## 其他语言版本
+### Java:
-Java:
```Java
class Solution {
public List
+
diff --git a/problems/0019.删除链表的倒数第N个节点.md b/problems/0019.删除链表的倒数第N个节点.md
index 84eac96b..1c95ad5b 100644
--- a/problems/0019.删除链表的倒数第N个节点.md
+++ b/problems/0019.删除链表的倒数第N个节点.md
@@ -7,7 +7,7 @@
-## 19.删除链表的倒数第N个节点
+# 19.删除链表的倒数第N个节点
[力扣题目链接](https://leetcode.cn/problems/remove-nth-node-from-end-of-list/)
@@ -31,11 +31,13 @@
输入:head = [1,2], n = 1
输出:[1]
+## 算法公开课
+
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)::[链表遍历学清楚! | LeetCode:19.删除链表倒数第N个节点](https://www.bilibili.com/video/BV1vW4y1U7Gf),相信结合视频再看本篇题解,更有助于大家对链表的理解。**
+
## 思路
-《代码随想录》算法公开课:[链表遍历学清楚! | LeetCode:19.删除链表倒数第N个节点](https://www.bilibili.com/video/BV1vW4y1U7Gf),相信结合视频在看本篇题解,更有助于大家对链表的理解。
-
双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。
@@ -93,7 +95,7 @@ public:
## 其他语言版本
-java:
+### Java:
```java
public ListNode removeNthFromEnd(ListNode head, int n){
@@ -120,7 +122,8 @@ public ListNode removeNthFromEnd(ListNode head, int n){
}
```
-Python:
+### Python:
+
```python
# Definition for singly-linked list.
# class ListNode:
@@ -151,7 +154,8 @@ class Solution:
return dummy_head.next
```
-Go:
+### Go:
+
```Go
/**
* Definition for singly-linked list.
@@ -178,7 +182,7 @@ func removeNthFromEnd(head *ListNode, n int) *ListNode {
}
```
-JavaScript:
+### JavaScript:
```js
/**
@@ -198,7 +202,7 @@ var removeNthFromEnd = function(head, n) {
return ret.next;
};
```
-TypeScript:
+### TypeScript:
版本一(快慢指针法):
@@ -263,7 +267,7 @@ function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
};
```
-Kotlin:
+### Kotlin:
```Kotlin
fun removeNthFromEnd(head: ListNode?, n: Int): ListNode? {
@@ -284,7 +288,8 @@ fun removeNthFromEnd(head: ListNode?, n: Int): ListNode? {
}
```
-Swift:
+### Swift:
+
```swift
func removeNthFromEnd(_ head: ListNode?, _ n: Int) -> ListNode? {
if head == nil {
@@ -309,8 +314,8 @@ func removeNthFromEnd(_ head: ListNode?, _ n: Int) -> ListNode? {
}
```
+### PHP:
-PHP:
```php
function removeNthFromEnd($head, $n) {
// 设置虚拟头节点
@@ -332,7 +337,8 @@ function removeNthFromEnd($head, $n) {
}
```
-Scala:
+### Scala:
+
```scala
object Solution {
def removeNthFromEnd(head: ListNode, n: Int): ListNode = {
@@ -356,7 +362,8 @@ object Solution {
}
```
-Rust:
+### Rust:
+
```rust
impl Solution {
pub fn remove_nth_from_end(head: Option参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!
-## 24. 两两交换链表中的节点 +# 24. 两两交换链表中的节点 [力扣题目链接](https://leetcode.cn/problems/swap-nodes-in-pairs/) @@ -16,9 +16,11 @@
-## 思路
+## 算法公开课
-《代码随想录》算法公开课:[帮你把链表细节学清楚! | LeetCode:24. 两两交换链表中的节点](https://www.bilibili.com/video/BV1YT411g7br),相信结合视频在看本篇题解,更有助于大家对链表的理解。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[帮你把链表细节学清楚! | LeetCode:24. 两两交换链表中的节点](https://www.bilibili.com/video/BV1YT411g7br),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+
+## 思路
这道题目正常模拟就可以了。
@@ -88,7 +90,8 @@ public:
## 其他语言版本
-C:
+### C:
+
```c
/**
* Definition for singly-linked list.
@@ -132,7 +135,7 @@ struct ListNode* swapPairs(struct ListNode* head){
}
```
-Java:
+### Java:
```Java
// 递归版本
@@ -176,7 +179,32 @@ class Solution {
}
```
-Python:
+### Python:
+
+```python
+# 递归版本
+# Definition for singly-linked list.
+# class ListNode:
+# def __init__(self, val=0, next=None):
+# self.val = val
+# self.next = next
+
+class Solution:
+ def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
+ if head is None or head.next is None:
+ return head
+
+ # 待翻转的两个node分别是pre和cur
+ pre = head
+ cur = head.next
+ next = head.next.next
+
+ cur.next = pre # 交换
+ pre.next = self.swapPairs(next) # 将以next为head的后续链表两两交换
+
+ return cur
+```
+
```python
# Definition for singly-linked list.
# class ListNode:
@@ -202,7 +230,8 @@ class Solution:
```
-Go:
+### Go:
+
```go
func swapPairs(head *ListNode) *ListNode {
dummy := &ListNode{
@@ -238,7 +267,8 @@ func swapPairs(head *ListNode) *ListNode {
}
```
-Javascript:
+### Javascript:
+
```javascript
var swapPairs = function (head) {
let ret = new ListNode(0, head), temp = ret;
@@ -253,7 +283,7 @@ var swapPairs = function (head) {
};
```
-TypeScript:
+### TypeScript:
```typescript
function swapPairs(head: ListNode | null): ListNode | null {
@@ -272,7 +302,7 @@ function swapPairs(head: ListNode | null): ListNode | null {
};
```
-Kotlin:
+### Kotlin:
```kotlin
fun swapPairs(head: ListNode?): ListNode? {
@@ -292,7 +322,8 @@ fun swapPairs(head: ListNode?): ListNode? {
}
```
-Swift:
+### Swift:
+
```swift
func swapPairs(_ head: ListNode?) -> ListNode? {
if head == nil || head?.next == nil {
@@ -313,7 +344,8 @@ func swapPairs(_ head: ListNode?) -> ListNode? {
return dummyHead.next
}
```
-Scala:
+### Scala:
+
```scala
// 虚拟头节点
object Solution {
@@ -337,7 +369,8 @@ object Solution {
}
```
-PHP:
+### PHP:
+
```php
//虚拟头结点
function swapPairs($head) {
@@ -380,7 +413,7 @@ function swapPairs($head)
}
```
-Rust:
+### Rust:
```rust
// 虚拟头节点
diff --git a/problems/0027.移除元素.md b/problems/0027.移除元素.md
index 90801153..ce9eccf0 100644
--- a/problems/0027.移除元素.md
+++ b/problems/0027.移除元素.md
@@ -5,7 +5,7 @@
参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!
-## 27. 移除元素 +# 27. 移除元素 [力扣题目链接](https://leetcode.cn/problems/remove-element/) @@ -26,9 +26,12 @@ **你不需要考虑数组中超出新长度后面的元素。** -## 思路 -针对本题,我录制了视频讲解:[数组中移除元素并不容易!LeetCode:27. 移除元素](https://www.bilibili.com/video/BV12A4y1Z7LP),结合本题解一起看,事半功倍! +## 算法公开课 + +**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[数组中移除元素并不容易!LeetCode:27. 移除元素](https://www.bilibili.com/video/BV12A4y1Z7LP),相信结合视频再看本篇题解,更有助于大家对本题的理解**。 + +## 思路 有的同学可能说了,多余的元素,删掉不就得了。 @@ -156,8 +159,8 @@ public: ## 其他语言版本 +### Java: -Java: ```java class Solution { public int removeElement(int[] nums, int val) { @@ -194,7 +197,7 @@ class Solution { } ``` -Python: +### Python: ``` python 3 @@ -230,8 +233,8 @@ class Solution: ``` +### Go: -Go: ```go func removeElement(nums []int, val int) int { length:=len(nums) @@ -272,7 +275,8 @@ func removeElement(nums []int, val int) int { } ``` -JavaScript: +### JavaScript: + ```javascript //时间复杂度:O(n) //空间复杂度:O(1) @@ -287,7 +291,7 @@ var removeElement = (nums, val) => { }; ``` -TypeScript: +### TypeScript: ```typescript function removeElement(nums: number[], val: number): number { @@ -302,7 +306,7 @@ function removeElement(nums: number[], val: number): number { }; ``` -Ruby: +### Ruby: ```ruby def remove_element(nums, val) @@ -316,7 +320,8 @@ def remove_element(nums, val) i end ``` -Rust: +### Rust: + ```rust impl Solution { pub fn remove_element(nums: &mut Vec
-
diff --git a/problems/0037.解数独.md b/problems/0037.解数独.md
index 6edd3c5b..1763063e 100644
--- a/problems/0037.解数独.md
+++ b/problems/0037.解数独.md
@@ -6,8 +6,7 @@
参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!
- -如果对回溯法理论还不清楚的同学,可以先看这个视频[视频来了!!带你学透回溯算法(理论篇)](https://mp.weixin.qq.com/s/wDd5azGIYWjbU0fdua_qBg) +> 如果对回溯法理论还不清楚的同学,可以先看这个视频[视频来了!!带你学透回溯算法(理论篇)](https://mp.weixin.qq.com/s/wDd5azGIYWjbU0fdua_qBg) # 37. 解数独 @@ -35,11 +34,9 @@ * 你可以假设给定的数独只有唯一解。 * 给定数独永远是 9x9 形式的。 -# 算法公开课 - -**《代码随想录》算法视频公开课:[回溯算法二维递归?解数独不过如此!| LeetCode:37. 解数独](https://www.bilibili.com/video/BV1TW4y1471V/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。 - +## 算法公开课 +**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[回溯算法二维递归?解数独不过如此!| LeetCode:37. 解数独](https://www.bilibili.com/video/BV1TW4y1471V/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。 ## 思路 @@ -764,3 +761,4 @@ object Solution {
+
diff --git a/problems/0039.组合总和.md b/problems/0039.组合总和.md
index 4d9466c3..2a36ce5a 100644
--- a/problems/0039.组合总和.md
+++ b/problems/0039.组合总和.md
@@ -39,11 +39,11 @@ candidates 中的数字可以无限制重复被选取。
[3,5]
]
-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[Leetcode:39. 组合总和讲解](https://www.bilibili.com/video/BV1KT4y1M7HJ),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[Leetcode:39. 组合总和讲解](https://www.bilibili.com/video/BV1KT4y1M7HJ),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
-# 思路
+## 思路
题目中的**无限制重复被选取,吓得我赶紧想想 出现0 可咋办**,然后看到下面提示:1 <= candidates[i] <= 200,我就放心了。
@@ -57,7 +57,7 @@ candidates 中的数字可以无限制重复被选取。
而在[77.组合](https://programmercarl.com/0077.组合.html)和[216.组合总和III](https://programmercarl.com/0216.组合总和III.html) 中都可以知道要递归K层,因为要取k个元素的组合。
-## 回溯三部曲
+### 回溯三部曲
* 递归函数参数
@@ -156,7 +156,7 @@ public:
};
```
-## 剪枝优化
+### 剪枝优化
在这个树形结构中:
@@ -217,7 +217,7 @@ public:
* 时间复杂度: O(n * 2^n),注意这只是复杂度的上界,因为剪枝的存在,真实的时间复杂度远小于此
* 空间复杂度: O(target)
-# 总结
+## 总结
本题和我们之前讲过的[77.组合](https://programmercarl.com/0077.组合.html)、[216.组合总和III](https://programmercarl.com/0216.组合总和III.html)有两点不同:
@@ -238,10 +238,10 @@ public:
-# 其他语言版本
+## 其他语言版本
-## Java
+### Java
```Java
// 剪枝优化
@@ -271,7 +271,7 @@ class Solution {
}
```
-## Python
+### Python
回溯(版本一)
@@ -370,7 +370,7 @@ class Solution:
```
-## Go
+### Go
主要在于递归中传递下一个数字
@@ -404,7 +404,7 @@ func dfs(candidates []int, start int, target int) {
}
```
-## JavaScript
+### JavaScript
```js
var combinationSum = function(candidates, target) {
@@ -430,7 +430,7 @@ var combinationSum = function(candidates, target) {
};
```
-## TypeScript
+### TypeScript
```typescript
function combinationSum(candidates: number[], target: number): number[][] {
@@ -456,7 +456,7 @@ function combinationSum(candidates: number[], target: number): number[][] {
};
```
-## Rust
+### Rust
```Rust
impl Solution {
@@ -485,7 +485,7 @@ impl Solution {
}
```
-## C
+### C
```c
int* path;
@@ -541,7 +541,7 @@ int** combinationSum(int* candidates, int candidatesSize, int target, int* retur
}
```
-## Swift
+### Swift
```swift
func combinationSum(_ candidates: [Int], _ target: Int) -> [[Int]] {
@@ -570,7 +570,7 @@ func combinationSum(_ candidates: [Int], _ target: Int) -> [[Int]] {
}
```
-## Scala
+### Scala
```scala
object Solution {
@@ -604,3 +604,4 @@ object Solution {
+
diff --git a/problems/0040.组合总和II.md b/problems/0040.组合总和II.md
index 9094020e..33e4a46f 100644
--- a/problems/0040.组合总和II.md
+++ b/problems/0040.组合总和II.md
@@ -41,13 +41,11 @@ candidates 中的每个数字在每个组合中只能使用一次。
]
```
-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[回溯算法中的去重,树层去重树枝去重,你弄清楚了没?| LeetCode:40.组合总和II](https://www.bilibili.com/video/BV12V4y1V73A),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[回溯算法中的去重,树层去重树枝去重,你弄清楚了没?| LeetCode:40.组合总和II](https://www.bilibili.com/video/BV12V4y1V73A),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
-
-
-# 思路
+## 思路
这道题目和[39.组合总和](https://programmercarl.com/0039.组合总和.html)如下区别:
@@ -86,7 +84,7 @@ candidates 中的每个数字在每个组合中只能使用一次。
可以看到图中,每个节点相对于 [39.组合总和](https://mp.weixin.qq.com/s/FLg8G6EjVcxBjwCbzpACPw)我多加了used数组,这个used数组下面会重点介绍。
-## 回溯三部曲
+### 回溯三部曲
* **递归函数参数**
@@ -217,7 +215,7 @@ public:
* 时间复杂度: O(n * 2^n)
* 空间复杂度: O(n)
-## 补充
+### 补充
这里直接用startIndex来去重也是可以的, 就不用used数组了。
@@ -257,7 +255,7 @@ public:
```
-# 总结
+## 总结
本题同样是求组合总和,但就是因为其数组candidates有重复元素,而要求不能有重复的组合,所以相对于[39.组合总和](https://programmercarl.com/0039.组合总和.html)难度提升了不少。
@@ -265,14 +263,10 @@ public:
所以Carl有必要把去重的这块彻彻底底的给大家讲清楚,**就连“树层去重”和“树枝去重”都是我自创的词汇,希望对大家理解有帮助!**
+## 其他语言版本
-
-
-# 其他语言版本
-
-
-## Java
+### Java
**使用标记数组**
```Java
class Solution {
@@ -355,7 +349,7 @@ class Solution {
}
```
-## Python
+### Python
回溯
```python
class Solution:
@@ -442,7 +436,7 @@ class Solution:
self.combinationSumHelper(candidates, target - candidates[i], i + 1, path, results)
path.pop()
```
-## Go
+### Go
主要在于如何在回溯中去重
**使用used数组**
@@ -518,7 +512,7 @@ func dfs(candidates []int, start int, target int) {
}
}
```
-## javaScript
+### JavaScript
```js
/**
@@ -588,7 +582,7 @@ var combinationSum2 = function(candidates, target) {
};
```
-## TypeScript
+### TypeScript
```typescript
function combinationSum2(candidates: number[], target: number): number[][] {
@@ -619,7 +613,7 @@ function combinationSum2(candidates: number[], target: number): number[][] {
};
```
-## Rust
+### Rust
```Rust
impl Solution {
@@ -654,7 +648,7 @@ impl Solution {
}
```
-## C
+### C
```c
int* path;
@@ -716,7 +710,7 @@ int** combinationSum2(int* candidates, int candidatesSize, int target, int* retu
}
```
-## Swift
+### Swift
```swift
func combinationSum2(_ candidates: [Int], _ target: Int) -> [[Int]] {
@@ -749,7 +743,7 @@ func combinationSum2(_ candidates: [Int], _ target: Int) -> [[Int]] {
```
-## Scala
+### Scala
```scala
object Solution {
@@ -784,3 +778,4 @@ object Solution {
+
diff --git a/problems/0046.全排列.md b/problems/0046.全排列.md
index de1af642..1f5263a7 100644
--- a/problems/0046.全排列.md
+++ b/problems/0046.全排列.md
@@ -24,9 +24,9 @@
]
-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[组合与排列的区别,回溯算法求解的时候,有何不同?| LeetCode:46.全排列](https://www.bilibili.com/video/BV19v4y1S79W/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[组合与排列的区别,回溯算法求解的时候,有何不同?| LeetCode:46.全排列](https://www.bilibili.com/video/BV19v4y1S79W/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -491,3 +491,4 @@ object Solution {
+
diff --git a/problems/0047.全排列II.md b/problems/0047.全排列II.md
index afede33a..4fed8a5c 100644
--- a/problems/0047.全排列II.md
+++ b/problems/0047.全排列II.md
@@ -31,9 +31,9 @@
* 1 <= nums.length <= 8
* -10 <= nums[i] <= 10
-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[回溯算法求解全排列,如何去重?| LeetCode:47.全排列 II](https://www.bilibili.com/video/BV1R84y1i7Tm/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[回溯算法求解全排列,如何去重?| LeetCode:47.全排列 II](https://www.bilibili.com/video/BV1R84y1i7Tm/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -58,7 +58,7 @@
在[46.全排列](https://programmercarl.com/0046.全排列.html)中已经详细讲解了排列问题的写法,在[40.组合总和II](https://programmercarl.com/0040.组合总和II.html) 、[90.子集II](https://programmercarl.com/0090.子集II.html)中详细讲解了去重的写法,所以这次我就不用回溯三部曲分析了,直接给出代码,如下:
-## C++代码
+
```CPP
class Solution {
@@ -170,7 +170,7 @@ if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == true) {
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
-```
+```
其实并不行,一定要加上 `used[i - 1] == false`或者`used[i - 1] == true`,因为 used[i - 1] 要一直是 true 或者一直是false 才可以,而不是 一会是true 一会又是false。 所以这个条件要写上。
@@ -179,7 +179,7 @@ if (i > 0 && nums[i] == nums[i - 1]) {
## 其他语言版本
-### java
+### Java
```java
class Solution {
@@ -221,7 +221,7 @@ class Solution {
}
```
-### python
+Python
```python
class Solution:
@@ -526,3 +526,4 @@ object Solution {
+
diff --git a/problems/0051.N皇后.md b/problems/0051.N皇后.md
index 13cdafb8..6bc4fa78 100644
--- a/problems/0051.N皇后.md
+++ b/problems/0051.N皇后.md
@@ -28,9 +28,9 @@ n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,
* 输入:n = 1
* 输出:[["Q"]]
-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[这就是传说中的N皇后? 回溯算法安排!| LeetCode:51.N皇后](https://www.bilibili.com/video/BV1Rd4y1c7Bq/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[这就是传说中的N皇后? 回溯算法安排!| LeetCode:51.N皇后](https://www.bilibili.com/video/BV1Rd4y1c7Bq/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -864,3 +864,4 @@ object Solution {
+
diff --git a/problems/0052.N皇后II.md b/problems/0052.N皇后II.md
index 90b920ba..ac774c83 100644
--- a/problems/0052.N皇后II.md
+++ b/problems/0052.N皇后II.md
@@ -43,13 +43,11 @@ n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并
".Q.."]
]
-# 思路
+## 思路
详看:[51.N皇后](https://mp.weixin.qq.com/s/lU_QwCMj6g60nh8m98GAWg) ,基本没有区别
-# C++代码
-
```CPP
class Solution {
private:
@@ -100,8 +98,9 @@ public:
};
```
-# 其他语言补充
-JavaScript
+## 其他语言补充
+### JavaScript
+
```javascript
var totalNQueens = function(n) {
let count = 0;
@@ -146,7 +145,7 @@ var totalNQueens = function(n) {
};
```
-TypeScript:
+### TypeScript
```typescript
// 0-该格为空,1-该格有皇后
@@ -199,7 +198,7 @@ function checkValid(chess: GridStatus[][], i: number, j: number, n: number): boo
}
```
-C
+### C
```c
//path[i]为在i行,path[i]列上存在皇后
@@ -258,7 +257,8 @@ int totalNQueens(int n){
return answer;
}
```
-Java
+### Java
+
```java
class Solution {
int count = 0;
@@ -310,4 +310,3 @@ class Solution {
-
diff --git a/problems/0059.螺旋矩阵II.md b/problems/0059.螺旋矩阵II.md
index b4dad9c3..f03fcdad 100644
--- a/problems/0059.螺旋矩阵II.md
+++ b/problems/0059.螺旋矩阵II.md
@@ -6,7 +6,7 @@
-## 59.螺旋矩阵II
+# 59.螺旋矩阵II
[力扣题目链接](https://leetcode.cn/problems/spiral-matrix-ii/)
@@ -22,9 +22,12 @@
[ 7, 6, 5 ]
]
-## 思路
-为了利于录友们理解,我特意录制了视频,[拿下螺旋矩阵!LeetCode:59.螺旋矩阵II](https://www.bilibili.com/video/BV1SL4y1N7mV),结合视频一起看,事半功倍!
+## 算法公开课
+
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[拿下螺旋矩阵!LeetCode:59.螺旋矩阵II](https://www.bilibili.com/video/BV1SL4y1N7mV),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+
+## 思路
这道题目可以说在面试中出现频率较高的题目,**本题并不涉及到什么算法,就是模拟过程,但却十分考察对代码的掌控能力。**
@@ -122,15 +125,15 @@ public:
## 类似题目
-* 54.螺旋矩阵
-* 剑指Offer 29.顺时针打印矩阵
+* [54.螺旋矩阵](https://leetcode.cn/problems/spiral-matrix/)
+* [剑指Offer 29.顺时针打印矩阵](https://leetcode.cn/problems/shun-shi-zhen-da-yin-ju-zhen-lcof/)
## 其他语言版本
-Java:
+### Java:
```Java
class Solution {
@@ -173,7 +176,7 @@ class Solution {
}
```
-python3:
+### python3:
```python
class Solution:
@@ -204,7 +207,7 @@ class Solution:
return nums
```
-javaScript
+### JavaScript:
```javascript
@@ -256,7 +259,7 @@ var generateMatrix = function(n) {
```
-TypeScript:
+### TypeScript:
```typescript
function generateMatrix(n: number): number[][] {
@@ -301,7 +304,7 @@ function generateMatrix(n: number): number[][] {
};
```
-Go:
+### Go:
```go
package main
@@ -394,7 +397,7 @@ func generateMatrix(n int) [][]int {
}
```
-Swift:
+### Swift:
```swift
func generateMatrix(_ n: Int) -> [[Int]] {
@@ -450,7 +453,7 @@ func generateMatrix(_ n: Int) -> [[Int]] {
}
```
-Rust:
+### Rust:
```rust
impl Solution {
@@ -503,7 +506,8 @@ impl Solution {
}
```
-PHP:
+### PHP:
+
```php
class Solution {
/**
@@ -545,7 +549,8 @@ class Solution {
}
```
-C:
+### C:
+
```c
int** generateMatrix(int n, int* returnSize, int** returnColumnSizes){
//初始化返回的结果数组的大小
@@ -604,7 +609,8 @@ int** generateMatrix(int n, int* returnSize, int** returnColumnSizes){
return ans;
}
```
-Scala:
+### Scala:
+
```scala
object Solution {
def generateMatrix(n: Int): Array[Array[Int]] = {
@@ -656,7 +662,8 @@ object Solution {
}
}
```
-C#:
+### C#:
+
```csharp
public class Solution {
public int[][] GenerateMatrix(int n) {
@@ -685,3 +692,4 @@ public class Solution {
+
diff --git a/problems/0077.组合.md b/problems/0077.组合.md
index 8ade6e11..8d448739 100644
--- a/problems/0077.组合.md
+++ b/problems/0077.组合.md
@@ -5,10 +5,6 @@
参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!
- - - - # 第77题. 组合 [力扣题目链接](https://leetcode.cn/problems/combinations/ ) @@ -27,13 +23,12 @@ [1,4], ] -# 算法公开课 +## 算法公开课 + +**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[带你学透回溯算法-组合问题(对应力扣题目:77.组合)](https://www.bilibili.com/video/BV1ti4y1L7cv),[组合问题的剪枝操作](https://www.bilibili.com/video/BV1wi4y157er),相信结合视频在看本篇题解,更有助于大家对本题的理解**。 -**《代码随想录》算法视频公开课:[带你学透回溯算法-组合问题(对应力扣题目:77.组合)](https://www.bilibili.com/video/BV1ti4y1L7cv),[组合问题的剪枝操作](https://www.bilibili.com/video/BV1wi4y157er),相信结合视频在看本篇题解,更有助于大家对本题的理解**。 - - -# 思路 +## 思路 本题是回溯法的经典题目。 @@ -108,7 +103,7 @@ for (int i = 1; i <= n; i++) { 在[关于回溯算法,你该了解这些!](https://programmercarl.com/回溯算法理论基础.html)中我们提到了回溯法三部曲,那么我们按照回溯法三部曲开始正式讲解代码了。 -## 回溯法三部曲 +### 回溯法三部曲 * 递归函数的返回值以及参数 @@ -345,11 +340,10 @@ public: - - ## 其他语言版本 + ### Java: 未剪枝优化 ```java @@ -474,7 +468,7 @@ func dfs(n int, k int, start int) { } ``` -### javascript +### Javascript 剪枝: @@ -774,3 +768,4 @@ object Solution {
+
diff --git a/problems/0077.组合优化.md b/problems/0077.组合优化.md
index 3926d006..9577d65f 100644
--- a/problems/0077.组合优化.md
+++ b/problems/0077.组合优化.md
@@ -7,8 +7,11 @@
# 77.组合优化
+## 算法公开课
-**《代码随想录》算法视频公开课:[组合问题的剪枝操作](https://www.bilibili.com/video/BV1wi4y157er),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[组合问题的剪枝操作](https://www.bilibili.com/video/BV1wi4y157er),相信结合视频在看本篇题解,更有助于大家对本题的理解。**
+
+## 思路
在[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)中,我们通过回溯搜索法,解决了n个数中求k个数的组合问题。
@@ -46,7 +49,7 @@ public:
};
```
-# 剪枝优化
+## 剪枝优化
我们说过,回溯法虽然是暴力搜索,但也有时候可以有点剪枝优化一下的。
@@ -135,7 +138,7 @@ public:
-# 总结
+## 总结
本篇我们针对求组合问题的回溯法代码做了剪枝优化,这个优化如果不画图的话,其实不好理解,也不好讲清楚。
@@ -143,14 +146,10 @@ public:
**就酱,学到了就帮Carl转发一下吧,让更多的同学知道这里!**
-
-
-
-
## 其他语言版本
+### Java
-Java:
```java
class Solution {
List
+
diff --git a/problems/0078.子集.md b/problems/0078.子集.md
index 21009f6a..5f3654de 100644
--- a/problems/0078.子集.md
+++ b/problems/0078.子集.md
@@ -27,12 +27,12 @@
[]
]
-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[回溯算法解决子集问题,树上节点都是目标集和! | LeetCode:78.子集](https://www.bilibili.com/video/BV1U84y1q7Ci),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[回溯算法解决子集问题,树上节点都是目标集和! | LeetCode:78.子集](https://www.bilibili.com/video/BV1U84y1q7Ci),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
-# 思路
+## 思路
求子集问题和[77.组合](https://programmercarl.com/0077.组合.html)和[131.分割回文串](https://programmercarl.com/0131.分割回文串.html)又不一样了。
@@ -52,7 +52,7 @@
从图中红线部分,可以看出**遍历这个树的时候,把所有节点都记录下来,就是要求的子集集合**。
-## 回溯三部曲
+### 回溯三部曲
* 递归函数参数
@@ -102,8 +102,6 @@ for (int i = startIndex; i < nums.size(); i++) {
}
```
-## C++代码
-
根据[关于回溯算法,你该了解这些!](https://programmercarl.com/回溯算法理论基础.html)给出的回溯算法模板:
```
@@ -158,7 +156,7 @@ public:
并不会,因为每次递归的下一层就是从i+1开始的。
-# 总结
+## 总结
相信大家经过了
* 组合问题:
@@ -178,10 +176,10 @@ public:
**而组合问题、分割问题是收集树形结构中叶子节点的结果**。
-# 其他语言版本
+## 其他语言版本
-## Java
+### Java
```java
class Solution {
List
+
diff --git a/problems/0090.子集II.md b/problems/0090.子集II.md
index 3238ee52..88c8bdad 100644
--- a/problems/0090.子集II.md
+++ b/problems/0090.子集II.md
@@ -3,8 +3,6 @@
参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!
- - # 90.子集II [力扣题目链接](https://leetcode.cn/problems/subsets-ii/) @@ -25,9 +23,9 @@ [] ] -# 算法公开课 +## 算法公开课 -**《代码随想录》算法视频公开课:[回溯算法解决子集问题,如何去重?| LeetCode:90.子集II](https://www.bilibili.com/video/BV1vm4y1F71J/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。 +**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[回溯算法解决子集问题,如何去重?| LeetCode:90.子集II](https://www.bilibili.com/video/BV1vm4y1F71J/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。 ## 思路 @@ -240,7 +238,7 @@ class Solution { -#### Python3 +### Python3 回溯 利用used数组去重 ```python @@ -646,3 +644,4 @@ object Solution {
+
diff --git a/problems/0093.复原IP地址.md b/problems/0093.复原IP地址.md
index 55e57dde..59cd92da 100644
--- a/problems/0093.复原IP地址.md
+++ b/problems/0093.复原IP地址.md
@@ -40,16 +40,12 @@
* 0 <= s.length <= 3000
* s 仅由数字组成
-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[93.复原IP地址](https://www.bilibili.com/video/BV1XP4y1U73i/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
-
-# 算法公开课
-
-**《代码随想录》算法视频公开课:[回溯算法如何分割字符串并判断是合法IP?| LeetCode:93.复原IP地址](https://www.bilibili.com/video/BV1XP4y1U73i/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[回溯算法如何分割字符串并判断是合法IP?| LeetCode:93.复原IP地址](https://www.bilibili.com/video/BV1XP4y1U73i/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
-# 思路
+## 思路
做这道题目之前,最好先把[131.分割回文串](https://programmercarl.com/0131.分割回文串.html)这个做了。
@@ -63,7 +59,7 @@

-## 回溯三部曲
+### 回溯三部曲
* 递归参数
@@ -134,7 +130,7 @@ for (int i = startIndex; i < s.size(); i++) {
}
```
-## 判断子串是否合法
+### 判断子串是否合法
最后就是在写一个判断段位是否是有效段位了。
@@ -169,8 +165,6 @@ bool isValid(const string& s, int start, int end) {
}
```
-## C++代码
-
根据[关于回溯算法,你该了解这些!](https://programmercarl.com/回溯算法理论基础.html)给出的回溯算法模板:
@@ -247,7 +241,7 @@ public:
* 时间复杂度: O(3^4),IP地址最多包含4个数字,每个数字最多有3种可能的分割方式,则搜索树的最大深度为4,每个节点最多有3个子节点。
* 空间复杂度: O(n)
-# 总结
+## 总结
在[131.分割回文串](https://programmercarl.com/0131.分割回文串.html)中我列举的分割字符串的难点,本题都覆盖了。
@@ -259,9 +253,9 @@ public:
-# 其他语言版本
+## 其他语言版本
-## java
+### Java
```java
class Solution {
@@ -402,7 +396,7 @@ class Solution {
```
-## python
+### Python
回溯(版本一)
```python
@@ -478,9 +472,7 @@ class Solution:
```
-
-
-## Go
+### Go
```go
var (
@@ -517,7 +509,7 @@ func dfs(s string, start int) {
}
```
-## JavaScript
+### JavaScript
```js
/**
@@ -547,7 +539,7 @@ var restoreIpAddresses = function(s) {
};
```
-## TypeScript
+### TypeScript
```typescript
function isValidIpSegment(str: string): boolean {
@@ -586,7 +578,7 @@ function restoreIpAddresses(s: string): string[] {
};
```
-## Rust
+### Rust
```Rust
impl Solution {
@@ -643,7 +635,7 @@ impl Solution {
}
```
-## C
+### C
```c
//记录结果
char** result;
@@ -719,7 +711,7 @@ char ** restoreIpAddresses(char * s, int* returnSize){
}
```
-## Swift
+### Swift
```swift
// 判断区间段是否合法
@@ -766,7 +758,7 @@ func restoreIpAddresses(_ s: String) -> [String] {
}
```
-## Scala
+### Scala
```scala
object Solution {
@@ -813,3 +805,4 @@ object Solution {
+
diff --git a/problems/0098.验证二叉搜索树.md b/problems/0098.验证二叉搜索树.md
index 95b657a5..a48ec065 100644
--- a/problems/0098.验证二叉搜索树.md
+++ b/problems/0098.验证二叉搜索树.md
@@ -20,18 +20,18 @@

-# 视频讲解
+## 算法公开课
-**《代码随想录》算法视频公开课:[你对二叉搜索树了解的还不够! | LeetCode:98.验证二叉搜索树](https://www.bilibili.com/video/BV18P411n7Q4),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[你对二叉搜索树了解的还不够! | LeetCode:98.验证二叉搜索树](https://www.bilibili.com/video/BV18P411n7Q4),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
-# 思路
+## 思路
要知道中序遍历下,输出的二叉搜索树节点的数值是有序序列。
有了这个特性,**验证二叉搜索树,就相当于变成了判断一个序列是不是递增的了。**
-## 递归法
+### 递归法
可以递归中序遍历将二叉搜索树转变成一个数组,代码如下:
@@ -211,7 +211,7 @@ public:
最后这份代码看上去整洁一些,思路也清晰。
-## 迭代法
+### 迭代法
可以用迭代法模拟二叉树中序遍历,对前中后序迭代法生疏的同学可以看这两篇[二叉树:听说递归能做的,栈也能做!](https://programmercarl.com/二叉树的迭代遍历.html),[二叉树:前中后序迭代方式统一写法](https://programmercarl.com/二叉树的统一迭代法.html)
@@ -245,7 +245,7 @@ public:
在[二叉树:二叉搜索树登场!](https://programmercarl.com/0700.二叉搜索树中的搜索.html)中我们分明写出了痛哭流涕的简洁迭代法,怎么在这里不行了呢,因为本题是要验证二叉搜索树啊。
-# 总结
+## 总结
这道题目是一个简单题,但对于没接触过的同学还是有难度的。
@@ -254,10 +254,10 @@ public:
只要把基本类型的题目都做过,总结过之后,思路自然就开阔了。
-# 其他语言版本
+## 其他语言版本
-## Java
+### Java
```Java
//使用統一迭代法
@@ -369,7 +369,7 @@ class Solution {
}
```
-## Python
+### Python
递归法(版本一)利用中序递增性质,转换成数组
```python
@@ -479,7 +479,7 @@ class Solution:
```
-## Go
+### Go
```Go
func isValidBST(root *TreeNode) bool {
@@ -526,7 +526,7 @@ func isValidBST(root *TreeNode) bool {
}
```
-## JavaScript
+### JavaScript
辅助数组解决
@@ -595,7 +595,7 @@ var isValidBST = function (root) {
};
```
-## TypeScript
+### TypeScript
> 辅助数组解决:
@@ -637,7 +637,7 @@ function isValidBST(root: TreeNode | null): boolean {
};
```
-## Scala
+### Scala
辅助数组解决:
```scala
@@ -682,7 +682,7 @@ object Solution {
}
```
-## rust
+### Rust
递归:
@@ -735,3 +735,4 @@ impl Solution {
+
diff --git a/problems/0101.对称二叉树.md b/problems/0101.对称二叉树.md
index 4418c62d..36b39740 100644
--- a/problems/0101.对称二叉树.md
+++ b/problems/0101.对称二叉树.md
@@ -13,9 +13,11 @@

-# 思路
+## 算法公开课
-《代码随想录》算法视频公开课:[同时操作两个二叉树 | LeetCode:101. 对称二叉树](https://www.bilibili.com/video/BV1ue4y1Y7Mf),相信结合视频在看本篇题解,更有助于大家对本题的理解。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[同时操作两个二叉树 | LeetCode:101. 对称二叉树](https://www.bilibili.com/video/BV1ue4y1Y7Mf), 相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+
+## 思路
**首先想清楚,判断对称二叉树要比较的是哪两个节点,要比较的可不是左右节点!**
@@ -41,7 +43,7 @@
那么我们先来看看递归法的代码应该怎么写。
-## 递归法
+### 递归法
递归三部曲
@@ -159,13 +161,13 @@ public:
**所以建议大家做题的时候,一定要想清楚逻辑,每一步做什么。把题目所有情况想到位,相应的代码写出来之后,再去追求简洁代码的效果。**
-## 迭代法
+### 迭代法
这道题目我们也可以使用迭代法,但要注意,这里的迭代法可不是前中后序的迭代写法,因为本题的本质是判断两个树是否是相互翻转的,其实已经不是所谓二叉树遍历的前中后序的关系了。
这里我们可以使用队列来比较两个树(根节点的左右子树)是否相互翻转,(**注意这不是层序遍历**)
-### 使用队列
+#### 使用队列
通过队列来判断根节点的左子树和右子树的内侧和外侧是否相等,如动画所示:
@@ -207,7 +209,7 @@ public:
};
```
-### 使用栈
+#### 使用栈
细心的话,其实可以发现,这个迭代法,其实是把左右两个子树要比较的元素顺序放进一个容器,然后成对成对的取出来进行比较,那么其实使用栈也是可以的。
@@ -254,12 +256,12 @@ public:
这两道题目基本和本题是一样的,只要稍加修改就可以AC。
-* 100.相同的树
-* 572.另一个树的子树
+* [100.相同的树](https://leetcode.cn/problems/same-tree/)
+* [572.另一个树的子树](https://leetcode.cn/problems/subtree-of-another-tree/)
-# 其他语言版本
+## 其他语言版本
-Java
+### Java:
```Java
/**
@@ -364,7 +366,7 @@ Java
```
-Python
+### Python:
递归法:
```python
@@ -470,7 +472,8 @@ class Solution:
return True
```
-Go
+### Go:
+
```go
/**
* Definition for a binary tree node.
@@ -521,8 +524,7 @@ func isSymmetric(root *TreeNode) bool {
}
```
-
-JavaScript
+### JavaScript:
递归判断是否为对称二叉树:
```javascript
@@ -610,7 +612,7 @@ var isSymmetric = function(root) {
};
```
-TypeScript:
+### TypeScript:
> 递归法
@@ -679,7 +681,7 @@ function isSymmetric(root: TreeNode | null): boolean {
};
```
-Swift:
+### Swift:
> 递归
```swift
@@ -761,7 +763,7 @@ func isSymmetric3(_ root: TreeNode?) -> Bool {
}
```
-Scala
+### Scala:
> 递归:
```scala
@@ -835,7 +837,7 @@ object Solution {
}
```
-## Rust
+### Rust:
递归:
```rust
@@ -900,3 +902,4 @@ impl Solution {
+
diff --git a/problems/0102.二叉树的层序遍历.md b/problems/0102.二叉树的层序遍历.md
index c2ad9508..ce9a247c 100644
--- a/problems/0102.二叉树的层序遍历.md
+++ b/problems/0102.二叉树的层序遍历.md
@@ -8,21 +8,23 @@
# 二叉树层序遍历登场!
-《代码随想录》算法视频公开课:[讲透二叉树的层序遍历 | 广度优先搜索 | LeetCode:102.二叉树的层序遍历](https://www.bilibili.com/video/BV1GY4y1u7b2),相信结合视频在看本篇题解,更有助于大家对本题的理解。
+## 算法公开课
+
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[讲透二叉树的层序遍历 | 广度优先搜索 | LeetCode:102.二叉树的层序遍历](https://www.bilibili.com/video/BV1GY4y1u7b2),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
学会二叉树的层序遍历,可以一口气打完以下十题:
-* 102.二叉树的层序遍历
-* 107.二叉树的层次遍历II
-* 199.二叉树的右视图
-* 637.二叉树的层平均值
-* 429.N叉树的层序遍历
-* 515.在每个树行中找最大值
-* 116.填充每个节点的下一个右侧节点指针
-* 117.填充每个节点的下一个右侧节点指针II
-* 104.二叉树的最大深度
-* 111.二叉树的最小深度
+* [102.二叉树的层序遍历](https://leetcode.cn/problems/binary-tree-level-order-traversal/)
+* [107.二叉树的层次遍历II](https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/)
+* [199.二叉树的右视图](https://leetcode.cn/problems/binary-tree-right-side-view/)
+* [637.二叉树的层平均值](https://leetcode.cn/problems/binary-tree-right-side-view/)
+* [429.N叉树的层序遍历](https://leetcode.cn/problems/n-ary-tree-level-order-traversal/)
+* [515.在每个树行中找最大值](https://leetcode.cn/problems/find-largest-value-in-each-tree-row/)
+* [116.填充每个节点的下一个右侧节点指针](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/)
+* [117.填充每个节点的下一个右侧节点指针II](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node-ii/)
+* [104.二叉树的最大深度](https://leetcode.cn/problems/maximum-depth-of-binary-tree/)
+* [111.二叉树的最小深度](https://leetcode.cn/problems/minimum-depth-of-binary-tree/)
@@ -31,7 +33,7 @@
-# 102.二叉树的层序遍历
+## 102.二叉树的层序遍历
[力扣题目链接](https://leetcode.cn/problems/binary-tree-level-order-traversal/)
@@ -39,7 +41,7 @@

-思路:
+### 思路
我们之前讲过了三篇关于二叉树的深度优先遍历的文章:
@@ -63,7 +65,7 @@
代码如下:**这份代码也可以作为二叉树层序遍历的模板,打十个就靠它了**。
-C++代码:
+c++代码如下:
```CPP
class Solution {
@@ -111,7 +113,9 @@ public:
};
```
-java:
+### 其他语言版本
+
+#### Java:
```Java
// 102.二叉树的层序遍历
@@ -167,7 +171,7 @@ class Solution {
}
```
-python3代码:
+#### Python:
```python
@@ -219,12 +223,9 @@ class Solution:
self.helper(node.left, level + 1, levels)
self.helper(node.right, level + 1, levels)
-
```
-
-
-go:
+#### Go:
```go
/**
@@ -320,7 +321,7 @@ func levelOrder(root *TreeNode) (res [][]int) {
}
```
-javascript代码:
+#### Javascript:
```javascript
var levelOrder = function(root) {
@@ -350,7 +351,7 @@ var levelOrder = function(root) {
```
-TypeScript:
+#### TypeScript:
```typescript
function levelOrder(root: TreeNode | null): number[][] {
@@ -377,7 +378,7 @@ function levelOrder(root: TreeNode | null): number[][] {
};
```
-Swift:
+#### Swift:
```swift
func levelOrder(_ root: TreeNode?) -> [[Int]] {
@@ -403,7 +404,7 @@ func levelOrder(_ root: TreeNode?) -> [[Int]] {
}
```
-Scala:
+#### Scala:
```scala
// 102.二叉树的层序遍历
@@ -430,7 +431,7 @@ object Solution {
}
```
-Rust:
+#### Rust:
```rust
use std::cell::RefCell;
@@ -466,7 +467,7 @@ impl Solution {
**此时我们就掌握了二叉树的层序遍历了,那么如下九道力扣上的题目,只需要修改模板的两三行代码(不能再多了),便可打倒!**
-# 107.二叉树的层次遍历 II
+## 107.二叉树的层次遍历 II
[力扣题目链接](https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/)
@@ -474,7 +475,7 @@ impl Solution {

-思路:
+### 思路
相对于102.二叉树的层序遍历,就是最后把result数组反转一下就可以了。
@@ -506,7 +507,9 @@ public:
};
```
-python代码:
+### 其他语言版本
+
+#### Python:
```python
class Solution:
@@ -537,7 +540,7 @@ class Solution:
return result[::-1]
```
-Java:
+#### Java:
```java
// 107. 二叉树的层序遍历 II
@@ -618,12 +621,10 @@ class Solution {
return ans;
}
-}
+
```
-
-
-go:
+#### Go:
```GO
/**
@@ -662,7 +663,7 @@ func levelOrderBottom(root *TreeNode) [][]int {
}
```
-javascript代码
+#### Javascript:
```javascript
var levelOrderBottom = function(root) {
@@ -688,7 +689,7 @@ var levelOrderBottom = function(root) {
};
```
-TypeScript:
+#### TypeScript:
```typescript
function levelOrderBottom(root: TreeNode | null): number[][] {
@@ -711,7 +712,7 @@ function levelOrderBottom(root: TreeNode | null): number[][] {
};
```
-Swift:
+#### Swift:
```swift
func levelOrderBottom(_ root: TreeNode?) -> [[Int]] {
@@ -737,8 +738,7 @@ func levelOrderBottom(_ root: TreeNode?) -> [[Int]] {
}
```
-
-Scala:
+#### Scala:
```scala
// 107.二叉树的层次遍历II
@@ -764,7 +764,10 @@ object Solution {
res.reverse.toList
}
-Rust:
+
+```
+
+#### Rust:
```rust
use std::cell::RefCell;
@@ -796,7 +799,7 @@ impl Solution {
}
```
-# 199.二叉树的右视图
+## 199.二叉树的右视图
[力扣题目链接](https://leetcode.cn/problems/binary-tree-right-side-view/)
@@ -804,7 +807,7 @@ impl Solution {

-思路:
+### 思路
层序遍历的时候,判断是否遍历到单层的最后面的元素,如果是,就放进result数组中,随后返回result就可以了。
@@ -832,7 +835,9 @@ public:
};
```
-python代码:
+### 其他语言版本
+
+#### Python:
```python
# Definition for a binary tree node.
@@ -866,8 +871,7 @@ class Solution:
return right_view
```
-
-Java:
+#### Java:
```java
// 199.二叉树的右视图
@@ -911,7 +915,7 @@ public class N0199 {
}
```
-go:
+#### Go:
```GO
/**
@@ -945,8 +949,7 @@ func rightSideView(root *TreeNode) []int {
}
```
-
-javascript代码:
+#### Javascript:
```javascript
var rightSideView = function(root) {
@@ -972,7 +975,7 @@ var rightSideView = function(root) {
};
```
-TypeScript:
+#### TypeScript:
```typescript
function rightSideView(root: TreeNode | null): number[] {
@@ -992,7 +995,7 @@ function rightSideView(root: TreeNode | null): number[] {
};
```
-Swift:
+#### Swift:
```swift
func rightSideView(_ root: TreeNode?) -> [Int] {
@@ -1017,7 +1020,7 @@ func rightSideView(_ root: TreeNode?) -> [Int] {
}
```
-Scala:
+#### Scala:
```scala
// 199.二叉树的右视图
@@ -1043,7 +1046,7 @@ object Solution {
}
```
-rust:
+#### Rust:
```rust
use std::cell::RefCell;
@@ -1076,7 +1079,7 @@ impl Solution {
}
```
-# 637.二叉树的层平均值
+## 637.二叉树的层平均值
[力扣题目链接](https://leetcode.cn/problems/average-of-levels-in-binary-tree/)
@@ -1084,7 +1087,7 @@ impl Solution {

-思路:
+### 思路
本题就是层序遍历的时候把一层求个总和在取一个均值。
@@ -1115,7 +1118,9 @@ public:
```
-python代码:
+### 其他语言版本
+
+#### Python:
```python
class Solution:
@@ -1155,7 +1160,7 @@ class Solution:
return averages
```
-java:
+#### Java:
```java
// 637. 二叉树的层平均值
@@ -1197,7 +1202,7 @@ public class N0637 {
}
```
-go:
+#### Go:
```GO
/**
@@ -1235,7 +1240,7 @@ func averageOfLevels(root *TreeNode) []float64 {
}
```
-javascript代码:
+#### Javascript:
```javascript
var averageOfLevels = function(root) {
@@ -1262,7 +1267,7 @@ var averageOfLevels = function(root) {
};
```
-TypeScript:
+#### TypeScript:
```typescript
function averageOfLevels(root: TreeNode | null): number[] {
@@ -1286,7 +1291,7 @@ function averageOfLevels(root: TreeNode | null): number[] {
};
```
-Swift:
+#### Swift:
```swift
func averageOfLevels(_ root: TreeNode?) -> [Double] {
@@ -1313,7 +1318,7 @@ func averageOfLevels(_ root: TreeNode?) -> [Double] {
}
```
-Scala:
+#### Scala:
```scala
// 637.二叉树的层平均值
@@ -1339,7 +1344,7 @@ object Solution {
}
```
-rust:
+#### Rust:
```rust
use std::cell::RefCell;
@@ -1372,7 +1377,7 @@ impl Solution {
}
```
-# 429.N叉树的层序遍历
+## 429.N叉树的层序遍历
[力扣题目链接](https://leetcode.cn/problems/n-ary-tree-level-order-traversal/)
@@ -1390,8 +1395,7 @@ impl Solution {
[5,6]
]
-
-思路:
+### 思路
这道题依旧是模板题,只不过一个节点有多个孩子了
@@ -1423,7 +1427,9 @@ public:
};
```
-python代码:
+### 其他语言版本
+
+#### Python:
```python
"""
@@ -1475,7 +1481,7 @@ class Solution:
return result
```
-java:
+#### Java:
```java
// 429. N 叉树的层序遍历
@@ -1535,8 +1541,7 @@ public class N0429 {
}
```
-
-go:
+#### Go:
```GO
/**
@@ -1567,7 +1572,7 @@ func levelOrder(root *Node) [][]int {
}
```
-JavaScript代码:
+#### JavaScript:
```JavaScript
var levelOrder = function(root) {
@@ -1596,7 +1601,7 @@ var levelOrder = function(root) {
};
```
-TypeScript:
+#### TypeScript:
```typescript
function levelOrder(root: Node | null): number[][] {
@@ -1618,7 +1623,7 @@ function levelOrder(root: Node | null): number[][] {
};
```
-Swift:
+#### Swift:
```swift
func levelOrder(_ root: Node?) -> [[Int]] {
@@ -1643,7 +1648,7 @@ func levelOrder(_ root: Node?) -> [[Int]] {
}
```
-Scala:
+#### Scala:
```scala
// 429.N叉树的层序遍历
@@ -1672,7 +1677,7 @@ object Solution {
}
```
-rust:
+#### Rust:
```rust
pub struct Solution;
@@ -1720,7 +1725,7 @@ impl Solution {
}
```
-# 515.在每个树行中找最大值
+## 515.在每个树行中找最大值
[力扣题目链接](https://leetcode.cn/problems/find-largest-value-in-each-tree-row/)
@@ -1728,7 +1733,7 @@ impl Solution {

-思路:
+### 思路
层序遍历,取每一层的最大值
@@ -1758,7 +1763,9 @@ public:
};
```
-python代码:
+### 其他语言版本
+
+#### Python:
```python
# Definition for a binary tree node.
@@ -1794,7 +1801,7 @@ class Solution:
return result
```
-java代码:
+#### Java:
```java
class Solution {
@@ -1820,7 +1827,7 @@ class Solution {
}
```
-go:
+#### Go:
```GO
/**
@@ -1864,7 +1871,7 @@ func max(x, y int) int {
}
```
-javascript代码:
+#### Javascript:
```javascript
var largestValues = function(root) {
@@ -1890,7 +1897,7 @@ var largestValues = function(root) {
};
```
-TypeScript:
+#### TypeScript:
```typescript
function largestValues(root: TreeNode | null): number[] {
@@ -1916,7 +1923,7 @@ function largestValues(root: TreeNode | null): number[] {
};
```
-Swift:
+#### Swift:
```swift
func largestValues(_ root: TreeNode?) -> [Int] {
@@ -1943,7 +1950,7 @@ func largestValues(_ root: TreeNode?) -> [Int] {
}
```
-Scala:
+#### Scala:
```scala
// 515.在每个树行中找最大值
@@ -1970,7 +1977,7 @@ object Solution {
}
```
-rust:
+#### Rust:
```rust
use std::cell::RefCell;
@@ -2002,7 +2009,7 @@ impl Solution {
}
```
-# 116.填充每个节点的下一个右侧节点指针
+## 116.填充每个节点的下一个右侧节点指针
[力扣题目链接](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/)
@@ -2024,7 +2031,7 @@ struct Node {

-思路:
+### 思路
本题依然是层序遍历,只不过在单层遍历的时候记录一下本层的头部节点,然后在遍历的时候让前一个节点指向本节点就可以了
@@ -2063,7 +2070,9 @@ public:
};
```
-java代码:
+### 其他语言版本
+
+#### Java:
```java
class Solution {
@@ -2093,7 +2102,7 @@ class Solution {
}
```
-python代码:
+#### Python:
```python
"""
@@ -2133,7 +2142,7 @@ class Solution:
return root
```
-go:
+#### Go:
```GO
/**
@@ -2173,7 +2182,7 @@ func connect(root *Node) *Node {
```
-JavaScript:
+#### JavaScript:
```javascript
/**
@@ -2209,7 +2218,7 @@ var connect = function(root) {
```
-TypeScript:
+#### TypeScript:
```typescript
function connect(root: Node | null): Node | null {
@@ -2234,7 +2243,7 @@ function connect(root: Node | null): Node | null {
};
```
-Swift:
+#### Swift:
```swift
func connect(_ root: Node?) -> Node? {
@@ -2266,7 +2275,7 @@ func connect(_ root: Node?) -> Node? {
}
```
-Scala:
+#### Scala:
```scala
// 116.填充每个节点的下一个右侧节点指针
@@ -2297,11 +2306,11 @@ object Solution {
}
```
-# 117.填充每个节点的下一个右侧节点指针II
+## 117.填充每个节点的下一个右侧节点指针II
[力扣题目链接](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node-ii/)
-思路:
+### 思路
这道题目说是二叉树,但116题目说是完整二叉树,其实没有任何差别,一样的代码一样的逻辑一样的味道
@@ -2339,7 +2348,9 @@ public:
};
```
-Java 代码:
+### 其他语言版本
+
+#### Java:
```java
// 二叉树之层次遍历
@@ -2377,7 +2388,7 @@ class Solution {
}
```
-python代码:
+#### Python:
```python
# 层序遍历解法
@@ -2420,7 +2431,7 @@ class Solution:
```
-go:
+#### Go:
```GO
/**
@@ -2459,7 +2470,7 @@ func connect(root *Node) *Node {
}
```
-JavaScript:
+#### JavaScript:
```javascript
/**
@@ -2494,7 +2505,7 @@ var connect = function(root) {
};
```
-TypeScript:
+#### TypeScript:
```typescript
function connect(root: Node | null): Node | null {
@@ -2519,7 +2530,7 @@ function connect(root: Node | null): Node | null {
};
```
-Swift:
+#### Swift:
```swift
func connect(_ root: Node?) -> Node? {
@@ -2551,7 +2562,7 @@ func connect(_ root: Node?) -> Node? {
}
```
-Scala:
+#### Scala:
```scala
// 117.填充每个节点的下一个右侧节点指针II
@@ -2582,7 +2593,7 @@ object Solution {
}
```
-# 104.二叉树的最大深度
+## 104.二叉树的最大深度
[力扣题目链接](https://leetcode.cn/problems/maximum-depth-of-binary-tree/)
@@ -2600,7 +2611,7 @@ object Solution {
返回它的最大深度 3 。
-思路:
+### 思路
使用迭代法的话,使用层序遍历是最为合适的,因为最大的深度就是二叉树的层数,和层序遍历的方式极其吻合。
@@ -2635,7 +2646,9 @@ public:
};
```
-Java:
+### 其他语言版本
+
+#### Java:
```Java
class Solution {
@@ -2661,7 +2674,7 @@ class Solution {
}
```
-Python:
+#### Python:
```python 3
# Definition for a binary tree node.
@@ -2691,7 +2704,7 @@ class Solution:
```
-Go:
+#### Go:
```go
/**
@@ -2726,7 +2739,7 @@ func maxDepth(root *TreeNode) int {
}
```
-JavaScript:
+#### JavaScript:
```javascript
/**
@@ -2759,7 +2772,7 @@ var maxDepth = function(root) {
};
```
-TypeScript:
+#### TypeScript:
```typescript
function maxDepth(root: TreeNode | null): number {
@@ -2779,7 +2792,7 @@ function maxDepth(root: TreeNode | null): number {
};
```
-Swift:
+#### Swift:
```swift
func maxDepth(_ root: TreeNode?) -> Int {
@@ -2804,7 +2817,7 @@ func maxDepth(_ root: TreeNode?) -> Int {
}
```
-Scala:
+#### Scala:
```scala
// 104.二叉树的最大深度
@@ -2829,7 +2842,7 @@ object Solution {
}
```
-rust:
+#### Rust:
```rust
use std::cell::RefCell;
@@ -2859,10 +2872,12 @@ impl Solution {
}
```
-# 111.二叉树的最小深度
+## 111.二叉树的最小深度
[力扣题目链接](https://leetcode.cn/problems/minimum-depth-of-binary-tree/)
+### 思路
+
相对于 104.二叉树的最大深度 ,本题还也可以使用层序遍历的方式来解决,思路是一样的。
**需要注意的是,只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点**
@@ -2895,7 +2910,9 @@ public:
};
```
-Java:
+### 其他语言版本
+
+#### Java:
```java
class Solution {
@@ -2925,9 +2942,7 @@ class Solution {
}
```
-
-
-Python 3:
+#### Python:
```python 3
# Definition for a binary tree node.
@@ -2960,7 +2975,7 @@ class Solution:
return depth
```
-Go:
+#### Go:
```go
/**
@@ -2999,7 +3014,7 @@ func minDepth(root *TreeNode) int {
}
```
-JavaScript:
+#### JavaScript:
```javascript
/**
@@ -3035,7 +3050,7 @@ var minDepth = function(root) {
};
```
-TypeScript:
+#### TypeScript:
```typescript
function minDepth(root: TreeNode | null): number {
@@ -3056,7 +3071,7 @@ function minDepth(root: TreeNode | null): number {
};
```
-Swift:
+#### Swift:
```swift
func minDepth(_ root: TreeNode?) -> Int {
@@ -3082,7 +3097,7 @@ func minDepth(_ root: TreeNode?) -> Int {
}
```
-Scala:
+#### Scala:
```scala
// 111.二叉树的最小深度
@@ -3108,7 +3123,7 @@ object Solution {
}
```
-rust:
+#### Rust:
```rust
use std::cell::RefCell;
@@ -3141,28 +3156,27 @@ impl Solution {
}
```
-# 总结
+## 总结
二叉树的层序遍历,**就是图论中的广度优先搜索在二叉树中的应用**,需要借助队列来实现(此时又发现队列的一个应用了)。
来吧,一口气打十个:
-* 102.二叉树的层序遍历
-* 107.二叉树的层次遍历II
-* 199.二叉树的右视图
-* 637.二叉树的层平均值
-* 429.N叉树的层序遍历
-* 515.在每个树行中找最大值
-* 116.填充每个节点的下一个右侧节点指针
-* 117.填充每个节点的下一个右侧节点指针II
-* 104.二叉树的最大深度
-* 111.二叉树的最小深度
+* [102.二叉树的层序遍历](https://leetcode.cn/problems/binary-tree-level-order-traversal/)
+* [107.二叉树的层次遍历II](https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/)
+* [199.二叉树的右视图](https://leetcode.cn/problems/binary-tree-right-side-view/)
+* [637.二叉树的层平均值](https://leetcode.cn/problems/binary-tree-right-side-view/)
+* [429.N叉树的层序遍历](https://leetcode.cn/problems/n-ary-tree-level-order-traversal/)
+* [515.在每个树行中找最大值](https://leetcode.cn/problems/find-largest-value-in-each-tree-row/)
+* [116.填充每个节点的下一个右侧节点指针](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/)
+* [117.填充每个节点的下一个右侧节点指针II](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node-ii/)
+* [104.二叉树的最大深度](https://leetcode.cn/problems/maximum-depth-of-binary-tree/)
+* [111.二叉树的最小深度](https://leetcode.cn/problems/minimum-depth-of-binary-tree/)
**致敬叶师傅!**
-
-
+
diff --git a/problems/0104.二叉树的最大深度.md b/problems/0104.二叉树的最大深度.md
index 7130867b..05044375 100644
--- a/problems/0104.二叉树的最大深度.md
+++ b/problems/0104.二叉树的最大深度.md
@@ -5,6 +5,7 @@
参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!
+ # 104.二叉树的最大深度 [力扣题目链接](https://leetcode.cn/problems/maximum-depth-of-binary-tree/) @@ -23,17 +24,19 @@ 返回它的最大深度 3 。 -# 思路 +## 算法公开课 + +**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[二叉树的高度和深度有啥区别?究竟用什么遍历顺序?很多录友搞不懂 | 104.二叉树的最大深度](https://www.bilibili.com/video/BV1Gd4y1V75u),相信结合视频再看本篇题解,更有助于大家对本题的理解**。 + +## 思路 看完本篇可以一起做了如下两道题目: -* 104.二叉树的最大深度 -* 559.n叉树的最大深度 - -《代码随想录》算法视频公开课:[二叉树的高度和深度有啥区别?究竟用什么遍历顺序?很多录友搞不懂 | 104.二叉树的最大深度](https://www.bilibili.com/video/BV1Gd4y1V75u),相信结合视频在看本篇题解,更有助于大家对本题的理解。 +* [104.二叉树的最大深度](https://leetcode.cn/problems/maximum-depth-of-binary-tree/) +* [559.n叉树的最大深度](https://leetcode.cn/problems/maximum-depth-of-n-ary-tree/) -## 递归法 +### 递归法 本题可以使用前序(中左右),也可以使用后序遍历(左右中),使用前序求的就是深度,使用后序求的是高度。 @@ -164,7 +167,7 @@ public: }; ``` -## 迭代法 +### 迭代法 使用迭代法的话,使用层序遍历是最为合适的,因为最大的深度就是二叉树的层数,和层序遍历的方式极其吻合。 @@ -202,10 +205,11 @@ public: }; ``` - 那么我们可以顺便解决一下n叉树的最大深度问题 -# 559.n叉树的最大深度 +## 相关题目推荐 + +### 559.n叉树的最大深度 [力扣题目链接](https://leetcode.cn/problems/maximum-depth-of-n-ary-tree/) @@ -219,11 +223,11 @@ public: 我们应返回其最大深度,3。 -思路: +### 思路 依然可以提供递归法和迭代法,来解决这个问题,思路是和二叉树思路一样的,直接给出代码如下: -## 递归法 +#### 递归法 c++代码: @@ -240,7 +244,7 @@ public: } }; ``` -## 迭代法 +#### 迭代法 依然是层序遍历,代码如下: @@ -267,11 +271,11 @@ public: }; ``` -# 其他语言版本 +## 其他语言版本 -## java +### Java: -### 104.二叉树的最大深度 +104.二叉树的最大深度 ```java class solution { @@ -344,7 +348,8 @@ class solution { } ``` -### 559.n叉树的最大深度 +559.n叉树的最大深度 + ```java class Solution { /*递归法,后序遍历求root节点的高度*/ @@ -391,9 +396,9 @@ class solution { } ``` -## python +### Python : -### 104.二叉树的最大深度 +104.二叉树的最大深度 递归法: ```python @@ -448,7 +453,7 @@ class Solution: ``` -### 559.n叉树的最大深度 +559.n叉树的最大深度 递归法: ```python @@ -522,9 +527,10 @@ class Solution: return max_depth ``` +### Go: + +104.二叉树的最大深度 -## go -### 104.二叉树的最大深度 ```go /** * definition for a binary tree node. @@ -574,7 +580,7 @@ func maxdepth(root *treenode) int { ``` -### 559. n叉树的最大深度 +559. n叉树的最大深度 ```go func maxDepth(root *Node) int { @@ -598,9 +604,9 @@ func maxDepth(root *Node) int { } ``` -## javascript +### Javascript : -### 104.二叉树的最大深度 +104.二叉树的最大深度 ```javascript var maxdepth = function(root) { @@ -649,7 +655,7 @@ var maxDepth = function(root) { }; ``` -### 559.n叉树的最大深度 +559.n叉树的最大深度 N叉树的最大深度 递归写法 ```js @@ -683,9 +689,9 @@ var maxDepth = function(root) { }; ``` -## TypeScript +### TypeScript: -### 104.二叉树的最大深度 +104.二叉树的最大深度 ```typescript // 后续遍历(自下而上) @@ -728,7 +734,7 @@ function maxDepth(root: TreeNode | null): number { }; ``` -### 559.n叉树的最大深度 +559.n叉树的最大深度 ```typescript // 后续遍历(自下而上) @@ -756,9 +762,9 @@ function maxDepth(root: TreeNode | null): number { ``` -## C +### C: -### 104.二叉树的最大深度 +104.二叉树的最大深度 二叉树最大深度递归 ```c @@ -814,9 +820,9 @@ int maxDepth(struct TreeNode* root){ } ``` -## Swift +### Swift: -### 104.二叉树的最大深度 +104.二叉树的最大深度 ```swift // 递归 - 后序 @@ -856,7 +862,7 @@ func maxDepth(_ root: TreeNode?) -> Int { } ``` -### 559.n叉树的最大深度 +559.n叉树的最大深度 ```swift // 递归 @@ -893,9 +899,10 @@ func maxDepth1(_ root: Node?) -> Int { } ``` -## Scala +### Scala: + +104.二叉树的最大深度 -### 104.二叉树的最大深度 递归法: ```scala object Solution { @@ -934,7 +941,7 @@ object Solution { } ``` -### 559.n叉树的最大深度 +559.n叉树的最大深度 递归法: ```scala @@ -972,8 +979,8 @@ object Solution { } ``` -## rust -### 0104.二叉树的最大深度 +### Rust: +0104.二叉树的最大深度 递归: ```rust diff --git a/problems/0106.从中序与后序遍历序列构造二叉树.md b/problems/0106.从中序与后序遍历序列构造二叉树.md index a0bab999..0144fc5c 100644 --- a/problems/0106.从中序与后序遍历序列构造二叉树.md +++ b/problems/0106.从中序与后序遍历序列构造二叉树.md @@ -29,9 +29,9 @@  -# 视频讲解 +## 算法公开课 -**《代码随想录》算法视频公开课:[坑很多!来看看你掉过几次坑 | LeetCode:106.从中序与后序遍历序列构造二叉树](https://www.bilibili.com/video/BV1vW4y1i7dn),相信结合视频在看本篇题解,更有助于大家对本题的理解**。 +**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[坑很多!来看看你掉过几次坑 | LeetCode:106.从中序与后序遍历序列构造二叉树](https://www.bilibili.com/video/BV1vW4y1i7dn),相信结合视频在看本篇题解,更有助于大家对本题的理解**。 ## 思路 @@ -158,8 +158,6 @@ root->right = traversal(rightInorder, rightPostorder); 完整代码如下: -### C++完整代码 - ```CPP class Solution { private: @@ -281,8 +279,6 @@ public: 下面给出用下标索引写出的代码版本:(思路是一样的,只不过不用重复定义vector了,每次用下标索引来分割) -### C++优化版本 - ```CPP class Solution { private: @@ -400,8 +396,9 @@ public: }; ``` +## 相关题目推荐 -# 105.从前序与中序遍历序列构造二叉树 +### 105.从前序与中序遍历序列构造二叉树 [力扣题目链接](https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/) @@ -418,7 +415,7 @@ public:  -## 思路 +### 思路 本题和106是一样的道理。 @@ -547,7 +544,7 @@ public: }; ``` -# 思考题 +## 思考题 前序和中序可以唯一确定一棵二叉树。 @@ -569,7 +566,7 @@ tree2 的前序遍历是[1 2 3], 后序遍历是[3 2 1]。 所以前序和后序不能唯一确定一棵二叉树! -# 总结 +## 总结 之前我们讲的二叉树题目都是各种遍历二叉树,这次开始构造二叉树了,思路其实比较简单,但是真正代码实现出来并不容易。 @@ -585,9 +582,9 @@ tree2 的前序遍历是[1 2 3], 后序遍历是[3 2 1]。 -# 其他语言版本 +## 其他语言版本 -## Java +### Java 106.从中序与后序遍历序列构造二叉树 @@ -688,7 +685,7 @@ class Solution { } ``` -## Python +### Python 105.从前序与中序遍历序列构造二叉树 @@ -754,7 +751,7 @@ class Solution: return root ``` -## Go +### Go 106 从中序与后序遍历序列构造二叉树 @@ -833,9 +830,7 @@ func build(pre []int, in []int, root int, l, r int) *TreeNode { ``` - - -## JavaScript +### JavaScript ```javascript var buildTree = function(inorder, postorder) { @@ -863,7 +858,7 @@ var buildTree = function(preorder, inorder) { }; ``` -## TypeScript +### TypeScript > 106.从中序与后序遍历序列构造二叉树 @@ -969,7 +964,7 @@ function buildTree(preorder: number[], inorder: number[]): TreeNode | null { }; ``` -## C +### C 106 从中序与后序遍历序列构造二叉树 @@ -1047,7 +1042,7 @@ struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int in } ``` -## Swift +### Swift 105 从前序与中序遍历序列构造二叉树 @@ -1140,7 +1135,7 @@ class Solution_0106 { } ``` -## Scala +### Scala 106 从中序与后序遍历序列构造二叉树 @@ -1188,7 +1183,7 @@ object Solution { } ``` -## rust +### Rust 106 从中序与后序遍历序列构造二叉树 @@ -1238,3 +1233,4 @@ impl Solution {
+
diff --git a/problems/0108.将有序数组转换为二叉搜索树.md b/problems/0108.将有序数组转换为二叉搜索树.md
index 056ef3e2..e699005e 100644
--- a/problems/0108.将有序数组转换为二叉搜索树.md
+++ b/problems/0108.将有序数组转换为二叉搜索树.md
@@ -20,11 +20,11 @@

-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[构造平衡二叉搜索树!| LeetCode:108.将有序数组转换为二叉搜索树](https://www.bilibili.com/video/BV1uR4y1X7qL?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[构造平衡二叉搜索树!| LeetCode:108.将有序数组转换为二叉搜索树](https://www.bilibili.com/video/BV1uR4y1X7qL?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
-# 思路
+## 思路
做这道题目之前大家可以了解一下这几道:
@@ -71,7 +71,7 @@
**这也是题目中强调答案不是唯一的原因。 理解这一点,这道题目算是理解到位了**。
-## 递归
+### 递归
递归三部曲:
@@ -155,7 +155,7 @@ public:
**注意:在调用traversal的时候传入的left和right为什么是0和nums.size() - 1,因为定义的区间为左闭右闭**。
-## 迭代法
+### 迭代法
迭代法可以通过三个队列来模拟,一个队列放遍历的节点,一个队列放左区间下标,一个队列放右区间下标。
@@ -203,7 +203,7 @@ public:
};
```
-# 总结
+## 总结
**在[二叉树:构造二叉树登场!](https://programmercarl.com/0106.从中序与后序遍历序列构造二叉树.html) 和 [二叉树:构造一棵最大的二叉树](https://programmercarl.com/0654.最大二叉树.html)之后,我们顺理成章的应该构造一下二叉搜索树了,一不小心还是一棵平衡二叉搜索树**。
@@ -216,10 +216,10 @@ public:
最后依然给出迭代的方法,其实就是模拟取中间元素,然后不断分割去构造二叉树的过程。
-# 其他语言版本
+## 其他语言版本
-## Java
+### Java
递归: 左闭右开 [left,right)
```Java
@@ -315,7 +315,7 @@ class Solution {
}
```
-## Python
+### Python
递归法
```python
class Solution:
@@ -377,7 +377,7 @@ class Solution:
```
-## Go
+### Go
递归(隐含回溯)
@@ -396,7 +396,7 @@ func sortedArrayToBST(nums []int) *TreeNode {
}
```
-## JavaScript
+### JavaScript
递归
```javascript
@@ -453,7 +453,7 @@ var sortedArrayToBST = function(nums) {
return root;
};
```
-## TypeScript
+### TypeScript
```typescript
function sortedArrayToBST(nums: number[]): TreeNode | null {
@@ -469,7 +469,7 @@ function sortedArrayToBST(nums: number[]): TreeNode | null {
};
```
-## C
+### C
递归
```c
@@ -490,7 +490,7 @@ struct TreeNode* sortedArrayToBST(int* nums, int numsSize) {
}
```
-## Scala
+### Scala
递归:
@@ -511,7 +511,7 @@ object Solution {
}
```
-## rust
+### Rust
递归:
@@ -536,3 +536,4 @@ impl Solution {
+
diff --git a/problems/0110.平衡二叉树.md b/problems/0110.平衡二叉树.md
index e10a612a..c7df9c8f 100644
--- a/problems/0110.平衡二叉树.md
+++ b/problems/0110.平衡二叉树.md
@@ -33,8 +33,9 @@
返回 false 。
+## 算法公开课
-**《代码随想录》算法视频公开课:[后序遍历求高度,高度判断是否平衡 | LeetCode:110.平衡二叉树](https://www.bilibili.com/video/BV1Ug411S7my),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[后序遍历求高度,高度判断是否平衡 | LeetCode:110.平衡二叉树](https://www.bilibili.com/video/BV1Ug411S7my),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
## 题外话
@@ -357,7 +358,7 @@ public:
## 其他语言版本
-### Java
+### Java:
```Java
class Solution {
@@ -498,7 +499,7 @@ class Solution {
}
```
-### Python
+### Python:
递归法:
@@ -620,7 +621,7 @@ class Solution:
height_map[real_node] = 1 + max(left, right)
return True
```
-### Go
+### Go:
```Go
func isBalanced(root *TreeNode) bool {
@@ -652,7 +653,7 @@ func max(a, b int) int {
}
```
-### JavaScript
+### JavaScript:
递归法:
@@ -723,7 +724,7 @@ var isBalanced = function (root) {
};
```
-### TypeScript
+### TypeScript:
```typescript
// 递归法
@@ -741,7 +742,7 @@ function isBalanced(root: TreeNode | null): boolean {
};
```
-### C
+### C:
递归法:
@@ -876,7 +877,7 @@ func getHeight(_ root: TreeNode?) -> Int {
}
```
-### rust
+### Rust:
递归
@@ -912,3 +913,4 @@ impl Solution {
+
diff --git a/problems/0111.二叉树的最小深度.md b/problems/0111.二叉树的最小深度.md
index a1fc8a93..61f9beb7 100644
--- a/problems/0111.二叉树的最小深度.md
+++ b/problems/0111.二叉树的最小深度.md
@@ -26,9 +26,11 @@
返回它的最小深度 2.
-# 思路
+## 算法公开课
-《代码随想录》算法视频公开课:[看起来好像做过,一写就错! | LeetCode:111.二叉树的最小深度](https://www.bilibili.com/video/BV1QD4y1B7e2),相信结合视频在看本篇题解,更有助于大家对本题的理解。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[看起来好像做过,一写就错! | LeetCode:111.二叉树的最小深度](https://www.bilibili.com/video/BV1QD4y1B7e2),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+
+## 思路
看完了这篇[104.二叉树的最大深度](https://programmercarl.com/0104.二叉树的最大深度.html),再来看看如何求最小深度。
@@ -52,7 +54,7 @@
什么是叶子节点,左右孩子都为空的节点才是叶子节点!
-## 递归法
+### 递归法
来来来,一起递归三部曲:
@@ -199,7 +201,7 @@ public:
};
```
-## 迭代法
+### 迭代法
相对于[104.二叉树的最大深度](https://programmercarl.com/0104.二叉树的最大深度.html),本题还可以使用层序遍历的方式来解决,思路是一样的。
@@ -237,10 +239,10 @@ public:
```
-# 其他语言版本
+## 其他语言版本
-## Java
+### Java:
```Java
class Solution {
@@ -300,7 +302,7 @@ class Solution {
}
```
-## Python
+### Python :
递归法(版本一)
@@ -400,9 +402,7 @@ class Solution:
return depth
```
-
-
-## Go
+### Go:
```go
/**
@@ -463,7 +463,7 @@ func minDepth(root *TreeNode) int {
```
-## JavaScript
+### JavaScript:
递归法:
@@ -509,7 +509,7 @@ var minDepth = function(root) {
};
```
-## TypeScript
+### TypeScript:
> 递归法
@@ -547,7 +547,7 @@ function minDepth(root: TreeNode | null): number {
};
```
-## Swift
+### Swift:
> 递归
```Swift
@@ -594,7 +594,7 @@ func minDepth(_ root: TreeNode?) -> Int {
```
-## Scala
+### Scala:
递归法:
```scala
@@ -633,7 +633,8 @@ object Solution {
}
```
-rust:
+### Rust:
+
```rust
impl Solution {
// 递归
diff --git a/problems/0112.路径总和.md b/problems/0112.路径总和.md
index 39285a3b..be03f719 100644
--- a/problems/0112.路径总和.md
+++ b/problems/0112.路径总和.md
@@ -21,9 +21,9 @@
返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。
-## 视频讲解
+## 算法公开课
-**《代码随想录》算法视频公开课:[拿不准的遍历顺序,搞不清的回溯过程,我太难了! | LeetCode:112. 路径总和](https://www.bilibili.com/video/BV19t4y1L7CR),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[拿不准的遍历顺序,搞不清的回溯过程,我太难了! | LeetCode:112. 路径总和](https://www.bilibili.com/video/BV19t4y1L7CR),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -32,8 +32,8 @@
那么接下来我通过详细讲解如下两道题,来回答这个问题:
-* 112.路径总和
-* 113.路径总和ii
+* [112.路径总和](https://leetcode.cn/problems/path-sum/)
+* [113.路径总和ii](https://leetcode.cn/problems/path-sum-ii/)
这道题我们要遍历从根节点到叶子节点的路径看看总和是不是目标和。
@@ -218,7 +218,9 @@ public:
如果大家完全理解了本题的递归方法之后,就可以顺便把leetcode上113. 路径总和ii做了。
-# 113. 路径总和ii
+## 相关题目推荐
+
+### 113. 路径总和ii
[力扣题目链接](https://leetcode.cn/problems/path-sum-ii/)
@@ -232,7 +234,7 @@ public:

-## 思路
+### 思路
113.路径总和ii要遍历整个树,找到所有路径,**所以递归函数不要返回值!**
@@ -289,7 +291,7 @@ public:
至于113. 路径总和ii 的迭代法我并没有写,用迭代方式记录所有路径比较麻烦,也没有必要,如果大家感兴趣的话,可以再深入研究研究。
-## 总结
+### 总结
本篇通过leetcode上112. 路径总和 和 113. 路径总和ii 详细的讲解了 递归函数什么时候需要返回值,什么不需要返回值。
@@ -300,11 +302,11 @@ public:
-# 其他语言版本
+## 其他语言版本
-## java
+### Java
-### 0112.路径总和
+0112.路径总和
```java
class solution {
@@ -422,7 +424,7 @@ class solution {
}
```
-### 0113.路径总和-ii
+0113.路径总和-ii
```java
class solution {
@@ -529,9 +531,9 @@ class Solution {
}
```
-## python
+### Python
-### 0112.路径总和
+0112.路径总和
(版本一) 递归
```python
@@ -618,7 +620,7 @@ class Solution:
-### 0113.路径总和-ii
+0113.路径总和-ii
(版本一) 递归
```python
@@ -719,9 +721,9 @@ class Solution:
```
-## go
+### Go
-### 112. 路径总和
+112. 路径总和
```go
//递归法
@@ -746,7 +748,7 @@ func hasPathSum(root *TreeNode, targetSum int) bool {
}
```
-### 113. 路径总和 II
+113. 路径总和 II
```go
/**
@@ -786,9 +788,9 @@ func traverse(node *TreeNode, result *[][]int, currPath *[]int, targetSum int) {
}
```
-## javascript
+### Javascript
-### 0112.路径总和
+0112.路径总和
**递归**
@@ -852,7 +854,7 @@ let hasPathSum = function(root, targetSum) {
};
```
-### 0113.路径总和-ii
+0113.路径总和-ii
**递归**
@@ -950,9 +952,9 @@ let pathSum = function(root, targetSum) {
};
```
-## TypeScript
+### TypeScript
-### 0112.路径总和
+0112.路径总和
**递归法:**
@@ -1034,7 +1036,7 @@ function hasPathSum(root: TreeNode | null, targetSum: number): boolean {
};
```
-### 0112.路径总和 ii
+0112.路径总和 ii
**递归法:**
@@ -1070,9 +1072,9 @@ function pathSum(root: TreeNode | null, targetSum: number): number[][] {
};
```
-## Swift
+### Swift
-### 0112.路径总和
+0112.路径总和
**递归**
@@ -1141,7 +1143,7 @@ func hasPathSum(_ root: TreeNode?, _ targetSum: Int) -> Bool {
}
```
-### 0113.路径总和 II
+0113.路径总和 II
**递归**
@@ -1192,10 +1194,11 @@ func traversal(_ cur: TreeNode?, count: Int) {
}
```
-## C
+### C
-> 0112.路径总和
-> 递归法:
+0112.路径总和
+
+递归法:
```c
bool hasPathSum(struct TreeNode* root, int targetSum){
@@ -1252,7 +1255,7 @@ bool hasPathSum(struct TreeNode* root, int targetSum){
}
```
-> 0113.路径总和 II
+0113.路径总和 II
```c
int** ret;
@@ -1317,9 +1320,9 @@ int** pathSum(struct TreeNode* root, int targetSum, int* returnSize, int** retur
}
```
-## Scala
+### Scala
-### 0112.路径总和
+0112.路径总和
**递归:**
@@ -1369,7 +1372,7 @@ object Solution {
}
```
-### 0113.路径总和 II
+0113.路径总和 II
**递归:**
@@ -1405,9 +1408,9 @@ object Solution {
}
```
-## rust
+### Rust
-### 112.路径总和.md
+0112.路径总和
递归:
@@ -1461,7 +1464,7 @@ impl Solution {
}
```
-### 113.路径总和-ii
+0113.路径总和-ii
```rust
impl Solution {
diff --git a/problems/0123.买卖股票的最佳时机III.md b/problems/0123.买卖股票的最佳时机III.md
index 6ac9a576..a646b7d5 100644
--- a/problems/0123.买卖股票的最佳时机III.md
+++ b/problems/0123.买卖股票的最佳时机III.md
@@ -413,7 +413,52 @@ function maxProfit(prices: number[]): number {
};
```
+Rust:
+> 版本一
+
+```rust
+impl Solution {
+ pub fn max_profit(prices: Vec
diff --git a/problems/0130.被围绕的区域.md b/problems/0130.被围绕的区域.md
index abb68e19..e244873b 100644
--- a/problems/0130.被围绕的区域.md
+++ b/problems/0130.被围绕的区域.md
@@ -188,6 +188,54 @@ class Solution {
}
}
```
+```Java
+//BFS(使用helper function)
+class Solution {
+ int[][] dir ={{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
+ public void solve(char[][] board) {
+ for(int i = 0; i < board.length; i++){
+ if(board[i][0] == 'O') bfs(board, i, 0);
+ if(board[i][board[0].length - 1] == 'O') bfs(board, i, board[0].length - 1);
+ }
+
+ for(int j = 1 ; j < board[0].length - 1; j++){
+ if(board[0][j] == 'O') bfs(board, 0, j);
+ if(board[board.length - 1][j] == 'O') bfs(board, board.length - 1, j);
+ }
+
+ for(int i = 0; i < board.length; i++){
+ for(int j = 0; j < board[0].length; j++){
+ if(board[i][j] == 'O') board[i][j] = 'X';
+ if(board[i][j] == 'A') board[i][j] = 'O';
+ }
+ }
+ }
+ private void bfs(char[][] board, int x, int y){
+ Queue
diff --git a/problems/0131.分割回文串.md b/problems/0131.分割回文串.md
index 92fed58a..ca73e9f7 100644
--- a/problems/0131.分割回文串.md
+++ b/problems/0131.分割回文串.md
@@ -23,12 +23,12 @@
["a","a","b"]
]
-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[131.分割回文串](https://www.bilibili.com/video/BV1c54y1e7k6),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[131.分割回文串](https://www.bilibili.com/video/BV1c54y1e7k6),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
-# 思路
+## 思路
本题这涉及到两个关键问题:
@@ -58,7 +58,7 @@
此时可以发现,切割问题的回溯搜索的过程和组合问题的回溯搜索的过程是差不多的。
-## 回溯三部曲
+### 回溯三部曲
* 递归函数参数
@@ -124,7 +124,7 @@ for (int i = startIndex; i < s.size(); i++) {
**注意切割过的位置,不能重复切割,所以,backtracking(s, i + 1); 传入下一层的起始位置为i + 1**。
-## 判断回文子串
+### 判断回文子串
最后我们看一下回文子串要如何判断了,判断一个字符串是否是回文。
@@ -147,8 +147,6 @@ for (int i = startIndex; i < s.size(); i++) {
此时关键代码已经讲解完毕,整体代码如下(详细注释了)
-## C++整体代码
-
根据Carl给出的回溯算法模板:
```CPP
@@ -212,7 +210,7 @@ public:
* 时间复杂度: O(n * 2^n)
* 空间复杂度: O(n^2)
-# 优化
+## 优化
上面的代码还存在一定的优化空间, 在于如何更高效的计算一个子字符串是否是回文字串。上述代码```isPalindrome```函数运用双指针的方法来判定对于一个字符串```s```, 给定起始下标和终止下标, 截取出的子字符串是否是回文字串。但是其中有一定的重复计算存在:
@@ -272,7 +270,7 @@ public:
```
-# 总结
+## 总结
这道题目在leetcode上是中等,但可以说是hard的题目了,但是代码其实就是按照模板的样子来的。
@@ -306,10 +304,10 @@ public:
-# 其他语言版本
+## 其他语言版本
-## Java
+### Java
```Java
class Solution {
List 参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!
diff --git a/problems/0200.岛屿数量.广搜版.md b/problems/0200.岛屿数量.广搜版.md
index 39af9f50..c20fe4f1 100644
--- a/problems/0200.岛屿数量.广搜版.md
+++ b/problems/0200.岛屿数量.广搜版.md
@@ -196,7 +196,51 @@ class Solution {
}
}
```
+
+## 其他语言版本
+### Python
+BFS solution
+```python
+class Solution:
+ def __init__(self):
+ self.dirs = [[0, 1], [1, 0], [-1, 0], [0, -1]]
+
+ def numIslands(self, grid: List[List[str]]) -> int:
+ m = len(grid)
+ n = len(grid[0])
+ visited = [[False]*n for _ in range(m)]
+ res = 0
+ for i in range(m):
+ for j in range(n):
+ if visited[i][j] == False and grid[i][j] == '1':
+ res += 1
+ self.bfs(grid, i, j, visited) # Call bfs within this condition
+ return res
+
+ def bfs(self, grid, i, j, visited):
+ q = deque()
+ q.append((i,j))
+ visited[i][j] = True
+ while q:
+ x, y = q.popleft()
+ for k in range(4):
+ next_i = x + self.dirs[k][0]
+ next_j = y + self.dirs[k][1]
+
+ if next_i < 0 or next_i >= len(grid):
+ continue
+ if next_j < 0 or next_j >= len(grid[0]):
+ continue
+ if visited[next_i][next_j]:
+ continue
+ if grid[next_i][next_j] == '0':
+ continue
+ q.append((next_i, next_j))
+ visited[next_i][next_j] = True
+```
+
参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益! 参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!
参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益! 参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!
diff --git a/problems/1971.寻找图中是否存在路径.md b/problems/1971.寻找图中是否存在路径.md
index 16c7cb1e..5f1d8943 100644
--- a/problems/1971.寻找图中是否存在路径.md
+++ b/problems/1971.寻找图中是否存在路径.md
@@ -31,9 +31,9 @@
## 思路
-本题是并查集基础题目。
+本题是并查集基础题目。 如果还不了解并查集,可以看这里:[并查集理论基础](https://programmercarl.com/图论并查集理论基础.html)
-首先要知道并查集可以解决什么问题呢?
+并查集可以解决什么问题呢?
主要就是集合问题,两个节点在不在一个集合,也可以将两个节点添加到一个集合中。
@@ -70,7 +70,7 @@ void join(int u, int v) {
}
```
-以上模板中,只要修改 n 大小就可以,本科n不会超过2 * 10^5。
+以上模板中,只要修改 n 大小就可以,本题n不会超过2 * 10^5。
并查集主要有三个功能。
diff --git a/problems/二叉树总结篇.md b/problems/二叉树总结篇.md
index 4c742a6b..82949543 100644
--- a/problems/二叉树总结篇.md
+++ b/problems/二叉树总结篇.md
@@ -92,7 +92,7 @@
* 递归:中序,双指针操作
* 迭代:模拟中序,逻辑相同
* [求二叉搜索树的众数](https://programmercarl.com/0501.二叉搜索树中的众数.html)
-
+
* 递归:中序,清空结果集的技巧,遍历一遍便可求众数集合
* [二叉搜索树转成累加树](https://programmercarl.com/0538.把二叉搜索树转换为累加树.html)
@@ -154,29 +154,13 @@
这个图是 [代码随想录知识星球](https://programmercarl.com/other/kstar.html) 成员:[青](https://wx.zsxq.com/dweb2/index/footprint/185251215558842),所画,总结的非常好,分享给大家。
-
**最后,二叉树系列就这么完美结束了,估计这应该是最长的系列了,感谢大家33天的坚持与陪伴,接下来我们又要开始新的系列了「回溯算法」!**
-
-
-## 其他语言版本
-
-
-Java:
-
-
-Python:
-
-
-Go:
-
-
-
-
参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益! 参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益! 参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!
参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益! 参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益! 参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益! 参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!> lists = new ArrayList<>();
@@ -351,7 +349,7 @@ class Solution {
}
```
-## Python
+### Python
回溯 基本版
```python
class Solution:
@@ -473,7 +471,7 @@ class Solution:
return all(s[i] == s[len(s) - 1 - i] for i in range(len(s) // 2))
```
-## Go
+### Go
```go
var (
path []string // 放已经回文的子串
@@ -512,7 +510,7 @@ func isPalindrome(s string) bool {
}
```
-## javaScript
+### JavaScript
```js
/**
@@ -545,7 +543,7 @@ var partition = function(s) {
};
```
-## TypeScript
+### TypeScript
```typescript
function partition(s: string): string[][] {
@@ -582,7 +580,7 @@ function partition(s: string): string[][] {
};
```
-## C
+### C
```c
char** path;
@@ -679,7 +677,7 @@ char*** partition(char* s, int* returnSize, int** returnColumnSizes){
}
```
-## Swift
+### Swift
```swift
func partition(_ s: String) -> [[String]] {
@@ -719,7 +717,7 @@ func partition(_ s: String) -> [[String]] {
}
```
-## Rust
+### Rust
**回溯+函数判断回文串**
```Rust
@@ -808,7 +806,7 @@ impl Solution {
```
-## Scala
+### Scala
```scala
object Solution {
@@ -855,3 +853,4 @@ object Solution {
+
diff --git a/problems/0349.两个数组的交集.md b/problems/0349.两个数组的交集.md
index c2f6ef46..8daf5a35 100644
--- a/problems/0349.两个数组的交集.md
+++ b/problems/0349.两个数组的交集.md
@@ -10,7 +10,7 @@
> 如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费!
-## 349. 两个数组的交集
+# 349. 两个数组的交集
[力扣题目链接](https://leetcode.cn/problems/intersection-of-two-arrays/)
@@ -22,9 +22,11 @@
输出结果中的每个元素一定是唯一的。
我们可以不考虑输出结果的顺序。
-## 思路
+## 算法公开课
-关于本题,我录制了讲解视频:[学透哈希表,set使用有技巧!Leetcode:349. 两个数组的交集](https://www.bilibili.com/video/BV1ba411S7wu),看视频配合题解,事半功倍。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)::[学透哈希表,set使用有技巧!Leetcode:349. 两个数组的交集](https://www.bilibili.com/video/BV1ba411S7wu),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+
+## 思路
这道题目,主要要学会使用一种哈希数据结构:unordered_set,这个数据结构可以解决很多类似的问题。
@@ -118,8 +120,7 @@ public:
## 其他语言版本
-
-Java:
+### Java:
```Java
import java.util.HashSet;
@@ -159,8 +160,9 @@ class Solution {
}
```
-Python3:
+### Python3:
(版本一) 使用字典和集合
+
```python
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
@@ -206,7 +208,8 @@ class Solution:
```
-Go:
+### Go:
+
```go
func intersection(nums1 []int, nums2 []int) []int {
set:=make(map[int]struct{},0) // 用map模拟set
@@ -227,7 +230,7 @@ func intersection(nums1 []int, nums2 []int) []int {
}
```
-javaScript:
+### JavaScript:
```js
/**
@@ -255,7 +258,7 @@ var intersection = function(nums1, nums2) {
};
```
-TypeScript:
+### TypeScript:
版本一(正常解法):
@@ -280,7 +283,7 @@ function intersection(nums1: number[], nums2: number[]): number[] {
};
```
-Swift:
+### Swift:
```swift
func intersection(_ nums1: [Int], _ nums2: [Int]) -> [Int] {
@@ -298,7 +301,8 @@ func intersection(_ nums1: [Int], _ nums2: [Int]) -> [Int] {
}
```
-PHP:
+### PHP:
+
```php
class Solution {
/**
@@ -327,7 +331,8 @@ class Solution {
}
```
-Rust:
+### Rust:
+
```rust
use std::collections::HashSet;
impl Solution {
@@ -363,7 +368,8 @@ impl Solution {
}
```
-C:
+### C:
+
```C
int* intersection1(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
@@ -394,7 +400,7 @@ int* intersection1(int* nums1, int nums1Size, int* nums2, int nums2Size, int* re
}
```
-Scala:
+### Scala:
正常解法:
```scala
@@ -439,8 +445,8 @@ object Solution {
```
+### C#:
-C#:
```csharp
public int[] Intersection(int[] nums1, int[] nums2) {
if(nums1==null||nums1.Length==0||nums2==null||nums1.Length==0)
@@ -461,11 +467,10 @@ C#:
```
## 相关题目
-* 350.两个数组的交集 II
+* [350.两个数组的交集 II](https://leetcode.cn/problems/intersection-of-two-arrays-ii/)
+
diff --git a/problems/0141.环形链表.md b/problems/0141.环形链表.md
index 7d7121a0..b1f42ba9 100644
--- a/problems/0141.环形链表.md
+++ b/problems/0141.环形链表.md
@@ -70,7 +70,7 @@ public:
## 其他语言版本
-### Java
+### Java:
```java
public class Solution {
@@ -90,7 +90,7 @@ public class Solution {
}
```
-### Python
+### Python:
```python
class Solution:
@@ -105,7 +105,7 @@ class Solution:
return False
```
-### Go
+### Go:
```go
func hasCycle(head *ListNode) bool {
@@ -125,7 +125,7 @@ func hasCycle(head *ListNode) bool {
}
```
-### JavaScript
+### JavaScript:
```js
var hasCycle = function(head) {
@@ -141,7 +141,7 @@ var hasCycle = function(head) {
};
```
-### TypeScript
+### TypeScript:
```typescript
function hasCycle(head: ListNode | null): boolean {
@@ -163,3 +163,4 @@ function hasCycle(head: ListNode | null): boolean {
+
diff --git a/problems/0142.环形链表II.md b/problems/0142.环形链表II.md
index f87d2cd9..d20101a7 100644
--- a/problems/0142.环形链表II.md
+++ b/problems/0142.环形链表II.md
@@ -11,7 +11,7 @@
> 找到有没有环已经很不容易了,还要让我找到环的入口?
-## 142.环形链表II
+# 142.环形链表II
[力扣题目链接](https://leetcode.cn/problems/linked-list-cycle-ii/)
@@ -24,9 +24,11 @@

-## 思路
+## 算法公开课
-《代码随想录》算法公开课:[把环形链表讲清楚!| LeetCode:142.环形链表II](https://www.bilibili.com/video/BV1if4y1d7ob),相信结合视频在看本篇题解,更有助于大家对链表的理解。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[把环形链表讲清楚!| LeetCode:142.环形链表II](https://www.bilibili.com/video/BV1if4y1d7ob),相信结合视频在看本篇题解,更有助于大家对链表的理解。**
+
+## 思路
这道题目,不仅考察对链表的操作,而且还需要一些数学运算。
@@ -148,7 +150,7 @@ public:
* 时间复杂度: O(n),快慢指针相遇前,指针走的次数小于链表长度,快慢指针相遇后,两个index指针走的次数也小于链表长度,总体为走的次数小于 2n
* 空间复杂度: O(1)
-## 补充
+### 补充
在推理过程中,大家可能有一个疑问就是:**为什么第一次在环中相遇,slow的 步数 是 x+y 而不是 x + 若干环的长度 + y 呢?**
@@ -190,8 +192,7 @@ public:
## 其他语言版本
-
-Java:
+### Java:
```java
public class Solution {
@@ -217,8 +218,7 @@ public class Solution {
}
```
-
-Python:
+### Python:
```python
(版本一)快慢指针法
@@ -270,7 +270,7 @@ class Solution:
return None
```
-Go:
+### Go:
```go
func detectCycle(head *ListNode) *ListNode {
@@ -290,7 +290,7 @@ func detectCycle(head *ListNode) *ListNode {
}
```
-javaScript
+### JavaScript
```js
// 两种循环实现方式
@@ -334,7 +334,7 @@ var detectCycle = function(head) {
};
```
-TypeScript:
+### TypeScript:
```typescript
function detectCycle(head: ListNode | null): ListNode | null {
@@ -356,7 +356,7 @@ function detectCycle(head: ListNode | null): ListNode | null {
};
```
-Swift:
+### Swift:
```swift
class Solution {
@@ -391,7 +391,7 @@ extension ListNode: Equatable {
}
```
-C:
+### C:
```c
ListNode *detectCycle(ListNode *head) {
@@ -410,7 +410,7 @@ ListNode *detectCycle(ListNode *head) {
}
```
-Scala:
+### Scala:
```scala
object Solution {
@@ -437,7 +437,7 @@ object Solution {
}
```
-C#:
+### C#:
```CSharp
public class Solution
{
diff --git a/problems/0150.逆波兰表达式求值.md b/problems/0150.逆波兰表达式求值.md
index 09cc4f96..663a68ea 100644
--- a/problems/0150.逆波兰表达式求值.md
+++ b/problems/0150.逆波兰表达式求值.md
@@ -5,8 +5,6 @@
+
diff --git a/problems/0188.买卖股票的最佳时机IV.md b/problems/0188.买卖股票的最佳时机IV.md
index 14f514a9..773a910a 100644
--- a/problems/0188.买卖股票的最佳时机IV.md
+++ b/problems/0188.买卖股票的最佳时机IV.md
@@ -474,6 +474,55 @@ function maxProfit(k: number, prices: number[]): number {
};
```
+Rust:
+
+```rust
+impl Solution {
+ pub fn max_profit(k: i32, prices: Vec
+```
diff --git a/problems/0200.岛屿数量.深搜版.md b/problems/0200.岛屿数量.深搜版.md
index 6d42162a..c30ace19 100644
--- a/problems/0200.岛屿数量.深搜版.md
+++ b/problems/0200.岛屿数量.深搜版.md
@@ -176,6 +176,48 @@ public void dfs(char[][] grid, int i, int j){
dfs(grid,i,j + 1);
dfs(grid,i,j - 1);
}
+```
+```java
+//graph - dfs (和卡哥的代碼邏輯一致)
+class Solution {
+ boolean[][] visited;
+ int dir[][] = {
+ {0, 1}, //right
+ {1, 0}, //down
+ {-1, 0}, //up
+ {0, -1} //left
+ };
+ public int numIslands(char[][] grid) {
+ int count = 0;
+ visited = new boolean[grid.length][grid[0].length];
+
+ for(int i = 0; i < grid.length; i++){
+ for(int j = 0; j < grid[0].length; j++){
+ if(visited[i][j] == false && grid[i][j] == '1'){
+ count++;
+ dfs(grid, i, j);
+ }
+ }
+ }
+ return count;
+ }
+
+ private void dfs(char[][]grid, int x, int y){
+ if(visited[x][y] == true || grid[x][y] == '0')
+ return;
+
+ visited[x][y] = true;
+
+ for(int i = 0; i < 4; i++){
+ int nextX = x + dir[i][0];
+ int nextY = y + dir[i][1];
+ if(nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length)
+ continue;
+ dfs(grid, nextX, nextY);
+ }
+ }
+}
+```
diff --git a/problems/0202.快乐数.md b/problems/0202.快乐数.md
index 7fe8cd8d..4a77e2b6 100644
--- a/problems/0202.快乐数.md
+++ b/problems/0202.快乐数.md
@@ -28,7 +28,7 @@
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1
-# 思路
+## 思路
这道题目看上去貌似一道数学问题,其实并不是!
@@ -80,10 +80,10 @@ public:
-# 其他语言版本
+## 其他语言版本
+### Java:
-Java:
```java
class Solution {
public boolean isHappy(int n) {
@@ -107,8 +107,9 @@ class Solution {
}
```
-Python:
+### Python:
(版本一)使用集合
+
```python
class Solution:
def isHappy(self, n: int) -> bool:
@@ -131,7 +132,7 @@ class Solution:
n, r = divmod(n, 10)
new_num += r ** 2
return new_num
- ```
+```
(版本二)使用集合
```python
class Solution:
@@ -146,7 +147,7 @@ class Solution:
if new_num==1: return True
else: n = new_num
return False
-```
+ ```
(版本三)使用数组
```python
class Solution:
@@ -161,7 +162,7 @@ class Solution:
if new_num==1: return True
else: n = new_num
return False
-```
+ ```
(版本四)使用快慢指针
```python
class Solution:
@@ -180,7 +181,7 @@ class Solution:
n, r = divmod(n, 10)
new_num += r ** 2
return new_num
-```
+ ```
(版本五)使用集合+精简
```python
class Solution:
@@ -192,7 +193,7 @@ class Solution:
return False
seen.add(n)
return True
-```
+ ```
(版本六)使用数组+精简
```python
class Solution:
@@ -204,8 +205,9 @@ class Solution:
return False
seen.append(n)
return True
-```
-Go:
+ ```
+### Go:
+
```go
func isHappy(n int) bool {
m := make(map[int]bool)
@@ -225,7 +227,7 @@ func getSum(n int) int {
}
```
-javaScript:
+### JavaScript:
```js
var isHappy = function (n) {
@@ -303,7 +305,7 @@ var isHappy = function(n) {
};
```
-TypeScript:
+### TypeScript:
```typescript
function isHappy(n: number): boolean {
@@ -322,7 +324,7 @@ function isHappy(n: number): boolean {
};
```
-Swift:
+### Swift:
```swift
// number 每个位置上的数字的平方和
@@ -355,7 +357,8 @@ func isHappy(_ n: Int) -> Bool {
}
```
-PHP:
+### PHP:
+
```php
class Solution {
/**
@@ -386,7 +389,8 @@ class Solution {
}
```
-Rust:
+### Rust:
+
```Rust
use std::collections::HashSet;
impl Solution {
@@ -416,7 +420,8 @@ impl Solution {
}
```
-C:
+### C:
+
```C
typedef struct HashNodeTag {
int key; /* num */
@@ -473,8 +478,8 @@ object Solution {
}
```
+### C#:
-C#:
```csharp
public class Solution {
private int getSum(int n) {
@@ -500,3 +505,4 @@ public class Solution {
+
diff --git a/problems/0203.移除链表元素.md b/problems/0203.移除链表元素.md
index f8751658..c8f802a1 100644
--- a/problems/0203.移除链表元素.md
+++ b/problems/0203.移除链表元素.md
@@ -27,10 +27,12 @@
输入:head = [7,7,7,7], val = 7
输出:[]
+## 算法公开课
-# 思路
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[链表基础操作| LeetCode:203.移除链表元素](https://www.bilibili.com/video/BV18B4y1s7R9),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
-为了方便大家理解,我特意录制了视频:[链表基础操作| LeetCode:203.移除链表元素](https://www.bilibili.com/video/BV18B4y1s7R9),结合视频在看本题解,事半功倍。
+
+## 思路
这里以链表 1 4 2 4 来举例,移除元素4。
@@ -86,9 +88,6 @@
最后呢在题目中,return 头结点的时候,别忘了 `return dummyNode->next;`, 这才是新的头结点
-
-# C++代码
-
**直接使用原来的链表来进行移除节点操作:**
```CPP
@@ -155,7 +154,7 @@ public:
## 其他语言版本
-C:
+### C:
用原来的链表操作:
```c
@@ -223,7 +222,7 @@ struct ListNode* removeElements(struct ListNode* head, int val){
}
```
-Java:
+### Java:
```java
/**
@@ -304,7 +303,7 @@ public ListNode removeElements(ListNode head, int val) {
}
```
-Python:
+### Python:
```python
(版本一)虚拟头节点法
@@ -330,7 +329,7 @@ class Solution:
```
-Go:
+### Go:
```go
/**
@@ -355,7 +354,7 @@ func removeElements(head *ListNode, val int) *ListNode {
}
```
-javaScript:
+### JavaScript:
```js
/**
@@ -377,7 +376,7 @@ var removeElements = function(head, val) {
};
```
-TypeScript:
+### TypeScript:
版本一(在原链表上直接删除):
@@ -433,7 +432,7 @@ function removeElements(head: ListNode | null, val: number): ListNode | null {
};
```
-Swift:
+### Swift:
```swift
/**
@@ -461,7 +460,7 @@ func removeElements(_ head: ListNode?, _ val: Int) -> ListNode? {
}
```
-PHP:
+### PHP:
```php
/**
@@ -489,7 +488,7 @@ func removeElements(head *ListNode, val int) *ListNode {
}
```
-RUST:
+### Rust:
```rust
// Definition for singly-linked list.
@@ -527,7 +526,7 @@ impl Solution {
}
```
-Scala:
+### Scala:
```scala
/**
@@ -560,7 +559,7 @@ object Solution {
}
```
-Kotlin:
+### Kotlin:
```kotlin
/**
@@ -596,7 +595,8 @@ class Solution {
}
```
-C#
+### C#
+
```CSharp
/**
* Definition for singly-linked list.
@@ -635,3 +635,4 @@ public class Solution
+
diff --git a/problems/0206.翻转链表.md b/problems/0206.翻转链表.md
index 0425e182..5a57939a 100644
--- a/problems/0206.翻转链表.md
+++ b/problems/0206.翻转链表.md
@@ -17,9 +17,12 @@
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
-# 思路
+## 算法公开课
-本题我录制了B站视频,[帮你拿下反转链表 | LeetCode:206.反转链表](https://www.bilibili.com/video/BV1nB4y1i7eL),相信结合视频在看本篇题解,更有助于大家对链表的理解。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[帮你拿下反转链表 | LeetCode:206.反转链表](https://www.bilibili.com/video/BV1nB4y1i7eL),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+
+
+## 思路
如果再定义一个新的链表,实现链表元素的反转,其实这是对内存空间的浪费。
@@ -46,9 +49,7 @@
最后,cur 指针已经指向了null,循环结束,链表也反转完毕了。 此时我们return pre指针就可以了,pre指针就指向了新的头结点。
-# C++代码
-
-## 双指针法
+### 双指针法
```CPP
class Solution {
public:
@@ -71,7 +72,7 @@ public:
* 时间复杂度: O(n)
* 空间复杂度: O(1)
-## 递归法
+### 递归法
递归法相对抽象一些,但是其实和双指针法是一样的逻辑,同样是当cur为空的时候循环结束,不断将cur指向pre的过程。
@@ -132,8 +133,8 @@ public:
## 其他语言版本
+### Java:
-Java:
```java
// 双指针
class Solution {
@@ -193,7 +194,8 @@ class Solution {
}
```
-Python
+### Python:
+
```python
(版本一)双指针法
# Definition for singly-linked list.
@@ -214,8 +216,6 @@ class Solution:
return pre
```
-Python递归法:
-
```python
(版本二)递归法
# Definition for singly-linked list.
@@ -237,7 +237,7 @@ class Solution:
-Go:
+### Go:
```go
//双指针
@@ -268,7 +268,7 @@ func help(pre, head *ListNode)*ListNode{
}
```
-javaScript:
+### JavaScript:
```js
/**
@@ -323,7 +323,7 @@ var reverseList = function(head) {
};
```
-TypeScript:
+### TypeScript:
```typescript
// 双指针法
@@ -371,7 +371,7 @@ function reverseList(head: ListNode | null): ListNode | null {
};
```
-Ruby:
+### Ruby:
```ruby
# 双指针
@@ -416,7 +416,8 @@ def reverse(pre, cur)
end
```
-Kotlin:
+### Kotlin:
+
```Kotlin
fun reverseList(head: ListNode?): ListNode? {
var pre: ListNode? = null
@@ -466,7 +467,8 @@ class Solution {
}
```
-Swift:
+### Swift:
+
```swift
/// 双指针法 (迭代)
/// - Parameter head: 头结点
@@ -503,8 +505,9 @@ func reverse(pre: ListNode?, cur: ListNode?) -> ListNode? {
}
```
-C:
+### C:
双指针法:
+
```c
struct ListNode* reverseList(struct ListNode* head){
//保存cur的下一个结点
@@ -544,7 +547,8 @@ struct ListNode* reverseList(struct ListNode* head){
-PHP:
+### PHP:
+
```php
// 双指针法:
function reverseList($head) {
@@ -560,8 +564,9 @@ function reverseList($head) {
}
```
-Scala:
+### Scala:
双指针法:
+
```scala
object Solution {
def reverseList(head: ListNode): ListNode = {
@@ -596,7 +601,7 @@ object Solution {
}
```
-Rust:
+### Rust:
双指针法:
```rust
@@ -635,7 +640,7 @@ impl Solution {
}
}
```
-C#:
+### C#:
三指针法, 感觉会更直观:
```cs
@@ -672,11 +677,11 @@ public class LinkNumbers
}
```
+## 其他解法
+### 使用虚拟头结点解决链表反转
-## 使用虚拟头结点解决链表翻转
-
-> 使用虚拟头结点,通过头插法实现链表的翻转(不需要栈)
+> 使用虚拟头结点,通过头插法实现链表的反转(不需要栈)
```java
// 迭代方法:增加虚头结点,使用头插法实现链表翻转
@@ -699,7 +704,7 @@ public static ListNode reverseList1(ListNode head) {
-## 使用栈解决反转链表的问题
+### 使用栈解决反转链表的问题
* 首先将所有的结点入栈
* 然后创建一个虚拟虚拟头结点,让cur指向虚拟头结点。然后开始循环出栈,每出来一个元素,就把它加入到以虚拟头结点为头结点的链表当中,最后返回即可。
@@ -738,4 +743,3 @@ public ListNode reverseList(ListNode head) {
-
diff --git a/problems/0209.长度最小的子数组.md b/problems/0209.长度最小的子数组.md
index d7ae4780..4b1d0e96 100644
--- a/problems/0209.长度最小的子数组.md
+++ b/problems/0209.长度最小的子数组.md
@@ -13,9 +13,9 @@
示例:
-输入:s = 7, nums = [2,3,1,2,4,3]
-输出:2
-解释:子数组 [4,3] 是该条件下的长度最小的子数组。
+* 输入:s = 7, nums = [2,3,1,2,4,3]
+* 输出:2
+* 解释:子数组 [4,3] 是该条件下的长度最小的子数组。
提示:
@@ -23,11 +23,14 @@
* 1 <= nums.length <= 10^5
* 1 <= nums[i] <= 10^5
-# 思路
+## 算法公开课
-为了易于大家理解,我特意录制了B站视频[拿下滑动窗口! | LeetCode 209 长度最小的子数组](https://www.bilibili.com/video/BV1tZ4y1q7XE),结合视频看本题解,事半功倍!
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[拿下滑动窗口! | LeetCode 209 长度最小的子数组](https://www.bilibili.com/video/BV1tZ4y1q7XE),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
-## 暴力解法
+
+## 思路
+
+### 暴力解法
这道题目暴力解法当然是 两个for循环,然后不断的寻找符合条件的子序列,时间复杂度很明显是O(n^2)。
@@ -61,7 +64,7 @@ public:
后面力扣更新了数据,暴力解法已经超时了。
-## 滑动窗口
+### 滑动窗口
接下来就开始介绍数组操作中另一个重要的方法:**滑动窗口**。
@@ -148,8 +151,8 @@ public:
## 其他语言版本
+### Java:
-Java:
```java
class Solution {
@@ -170,7 +173,7 @@ class Solution {
}
```
-Python:
+### Python:
```python
(版本一)滑动窗口法
@@ -213,7 +216,8 @@ class Solution:
return min_len if min_len != float('inf') else 0
```
-Go:
+### Go:
+
```go
func minSubArrayLen(target int, nums []int) int {
i := 0
@@ -239,8 +243,7 @@ func minSubArrayLen(target int, nums []int) int {
}
```
-
-JavaScript:
+### JavaScript:
```js
var minSubArrayLen = function(target, nums) {
@@ -263,7 +266,7 @@ var minSubArrayLen = function(target, nums) {
};
```
-Typescript:
+### Typescript:
```typescript
function minSubArrayLen(target: number, nums: number[]): number {
@@ -285,7 +288,7 @@ function minSubArrayLen(target: number, nums: number[]): number {
};
```
-Swift:
+### Swift:
```swift
func minSubArrayLen(_ target: Int, _ nums: [Int]) -> Int {
@@ -306,7 +309,7 @@ func minSubArrayLen(_ target: Int, _ nums: [Int]) -> Int {
}
```
-Rust:
+### Rust:
```rust
impl Solution {
@@ -333,7 +336,8 @@ impl Solution {
}
```
-PHP:
+### PHP:
+
```php
// 双指针 - 滑动窗口
class Solution {
@@ -362,7 +366,7 @@ class Solution {
}
```
-Ruby:
+### Ruby:
```ruby
def min_sub_array_len(target, nums)
@@ -380,8 +384,9 @@ def min_sub_array_len(target, nums)
end
```
-C:
+### C:
暴力解法:
+
```c
int minSubArrayLen(int target, int* nums, int numsSize){
//初始化最小长度为INT_MAX
@@ -430,7 +435,8 @@ int minSubArrayLen(int target, int* nums, int numsSize){
}
```
-Kotlin:
+### Kotlin:
+
```kotlin
class Solution {
fun minSubArrayLen(target: Int, nums: IntArray): Int {
@@ -482,7 +488,7 @@ class Solution {
}
}
```
-Scala:
+### Scala:
滑动窗口:
```scala
@@ -530,7 +536,8 @@ object Solution {
}
}
```
-C#:
+### C#:
+
```csharp
public class Solution {
public int MinSubArrayLen(int s, int[] nums) {
@@ -556,3 +563,4 @@ public class Solution {
+
diff --git a/problems/0216.组合总和III.md b/problems/0216.组合总和III.md
index 319b2eba..4de7dc58 100644
--- a/problems/0216.组合总和III.md
+++ b/problems/0216.组合总和III.md
@@ -7,8 +7,6 @@
-
-
> 别看本篇选的是组合总和III,而不是组合总和,本题和上一篇77.组合相比难度刚刚好!
# 216.组合总和III
@@ -30,12 +28,12 @@
输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]
-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[和组合问题有啥区别?回溯算法如何剪枝?| LeetCode:216.组合总和III](https://www.bilibili.com/video/BV1wg411873x),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[和组合问题有啥区别?回溯算法如何剪枝?| LeetCode:216.组合总和III](https://www.bilibili.com/video/BV1wg411873x),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
-# 思路
+## 思路
本题就是在[1,2,3,4,5,6,7,8,9]这个集合中找到和为n的k个数的组合。
@@ -54,7 +52,7 @@
图中,可以看出,只有最后取到集合(1,3)和为4 符合条件。
-## 回溯三部曲
+### 回溯三部曲
* **确定递归函数参数**
@@ -165,7 +163,7 @@ public:
};
```
-## 剪枝
+### 剪枝
这道题目,剪枝操作其实是很容易想到了,想必大家看上面的树形图的时候已经想到了。
@@ -238,7 +236,7 @@ public:
* 时间复杂度: O(n * 2^n)
* 空间复杂度: O(n)
-# 总结
+## 总结
开篇就介绍了本题与[77.组合](https://programmercarl.com/0077.组合.html)的区别,相对来说加了元素总和的限制,如果做完[77.组合](https://programmercarl.com/0077.组合.html)再做本题在合适不过。
@@ -249,10 +247,10 @@ public:
-# 其他语言版本
+## 其他语言版本
-## Java
+### Java
模板方法
@@ -358,7 +356,7 @@ class Solution {
}
```
-## Python
+### Python
```py
class Solution:
@@ -383,7 +381,7 @@ class Solution:
```
-## Go
+### Go
回溯+减枝
@@ -418,7 +416,7 @@ func dfs(k, n int, start int, sum int) {
}
```
-## javaScript
+### JavaScript
```js
/**
@@ -455,7 +453,7 @@ var combinationSum3 = function(k, n) {
};
```
-## TypeScript
+### TypeScript
```typescript
function combinationSum3(k: number, n: number): number[][] {
@@ -479,7 +477,7 @@ function combinationSum3(k: number, n: number): number[][] {
};
```
-## Rust
+### Rust
```Rust
impl Solution {
@@ -516,7 +514,7 @@ impl Solution {
}
```
-## C
+### C
```c
int* path;
@@ -575,7 +573,7 @@ int** combinationSum3(int k, int n, int* returnSize, int** returnColumnSizes){
}
```
-## Swift
+### Swift
```swift
func combinationSum3(_ count: Int, _ targetSum: Int) -> [[Int]] {
@@ -607,7 +605,7 @@ func combinationSum3(_ count: Int, _ targetSum: Int) -> [[Int]] {
}
```
-## Scala
+### Scala
```scala
object Solution {
diff --git a/problems/0222.完全二叉树的节点个数.md b/problems/0222.完全二叉树的节点个数.md
index 795a6f37..d54f9b85 100644
--- a/problems/0222.完全二叉树的节点个数.md
+++ b/problems/0222.完全二叉树的节点个数.md
@@ -29,14 +29,17 @@
* 0 <= Node.val <= 5 * 10^4
* 题目数据保证输入的树是 完全二叉树
+## 算法公开课
-# 思路
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[要理解普通二叉树和完全二叉树的区别! | LeetCode:222.完全二叉树节点的数量](https://www.bilibili.com/video/BV1eW4y1B7pD),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+
+
+## 思路
-《代码随想录》算法视频公开课:[要理解普通二叉树和完全二叉树的区别! | LeetCode:222.完全二叉树节点的数量](https://www.bilibili.com/video/BV1eW4y1B7pD),相信结合视频在看本篇题解,更有助于大家对本题的理解。
本篇给出按照普通二叉树的求法以及利用完全二叉树性质的求法。
-## 普通二叉树
+### 普通二叉树
首先按照普通二叉树的逻辑来求。
@@ -44,7 +47,7 @@
递归遍历的顺序依然是后序(左右中)。
-### 递归
+#### 递归
如果对求二叉树深度还不熟悉的话,看这篇:[二叉树:看看这些树的最大深度](https://programmercarl.com/0104.二叉树的最大深度.html)。
@@ -112,7 +115,7 @@ public:
**网上基本都是这个精简的代码版本,其实不建议大家照着这个来写,代码确实精简,但隐藏了一些内容,连遍历的顺序都看不出来,所以初学者建议学习版本一的代码,稳稳的打基础**。
-### 迭代法
+#### 迭代
如果对求二叉树层序遍历还不熟悉的话,看这篇:[二叉树:层序遍历登场!](https://programmercarl.com/0102.二叉树的层序遍历.html)。
@@ -142,7 +145,7 @@ public:
* 时间复杂度:O(n)
* 空间复杂度:O(n)
-## 完全二叉树
+### 完全二叉树
以上方法都是按照普通二叉树来做的,对于完全二叉树特性不了解的同学可以看这篇 [关于二叉树,你该了解这些!](https://programmercarl.com/二叉树理论基础.html),这篇详细介绍了各种二叉树的特性。
@@ -249,9 +252,9 @@ public:
* 时间复杂度:O(log n × log n)
* 空间复杂度:O(log n)
-# 其他语言版本
+## 其他语言版本
-## Java
+### Java:
```java
class Solution {
// 通用递归解法
@@ -312,7 +315,7 @@ class Solution {
}
```
-## Python
+### Python:
递归法:
```python
@@ -408,7 +411,7 @@ class Solution: # 利用完全二叉树特性
return 1+self.countNodes(root.left)+self.countNodes(root.right)
```
-## Go
+### Go:
递归版本
@@ -488,9 +491,7 @@ func countNodes(root *TreeNode) int {
}
```
-
-
-## JavaScript:
+### JavaScript:
递归版本
```javascript
@@ -559,7 +560,7 @@ var countNodes = function(root) {
};
```
-## TypeScrpt:
+### TypeScrpt:
> 递归法
@@ -614,7 +615,7 @@ function countNodes(root: TreeNode | null): number {
};
```
-## C:
+### C:
递归法
```c
@@ -690,7 +691,7 @@ int countNodes(struct TreeNode* root){
}
```
-## Swift:
+### Swift:
> 递归
```swift
@@ -758,7 +759,7 @@ func countNodes(_ root: TreeNode?) -> Int {
}
```
-## Scala
+### Scala:
递归:
```scala
@@ -821,9 +822,9 @@ object Solution {
}
```
-rust:
+### Rust:
-// 递归
+递归
```rust
use std::cell::RefCell;
use std::rc::Rc;
@@ -838,7 +839,7 @@ impl Solution {
}
```
-// 迭代
+迭代
```rust
use std::rc::Rc;
use std::cell::RefCell;
diff --git a/problems/0225.用队列实现栈.md b/problems/0225.用队列实现栈.md
index 94c79404..13b742f8 100644
--- a/problems/0225.用队列实现栈.md
+++ b/problems/0225.用队列实现栈.md
@@ -25,11 +25,11 @@
* 你所使用的语言也许不支持队列。 你可以使用 list 或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
* 你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)。
+## 算法公开课
-# 思路
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[队列的基本操作! | LeetCode:225. 用队列实现栈](https://www.bilibili.com/video/BV1Fd4y1K7sm),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
-
-《代码随想录》算法公开课:[队列的基本操作! | LeetCode:225. 用队列实现栈](https://www.bilibili.com/video/BV1Fd4y1K7sm),相信结合视频再看本篇题解,更有助于大家对链表的理解。
+## 思路
(这里要强调是单向队列)
@@ -114,7 +114,7 @@ public:
* 时间复杂度: push为O(n),其他为O(1)
* 空间复杂度: O(n)
-# 优化
+## 优化
其实这道题目就是用一个队列就够了。
@@ -162,9 +162,9 @@ public:
* 空间复杂度: O(n)
-# 其他语言版本
+## 其他语言版本
-Java:
+### Java:
使用两个 Queue 实现方法1
```java
@@ -404,7 +404,7 @@ class MyStack {
}
```
-Python:
+### Python:
```python
from collections import deque
@@ -496,8 +496,7 @@ class MyStack:
return not self.que
```
-
-Go:
+### Go:
使用两个队列实现
```go
@@ -628,9 +627,7 @@ func (this *MyStack) Empty() bool {
*/
```
-
-
-javaScript:
+### JavaScript:
使用数组(push, shift)模拟队列
@@ -740,7 +737,7 @@ MyStack.prototype.empty = function() {
```
-TypeScript:
+### TypeScript:
版本一:使用两个队列模拟栈
@@ -812,7 +809,7 @@ class MyStack {
}
```
-Swift
+### Swift:
```Swift
// 定义一个队列数据结构
@@ -931,8 +928,9 @@ class MyStack {
}
}
```
-Scala:
+### Scala:
使用两个队列模拟栈:
+
```scala
import scala.collection.mutable
@@ -1015,8 +1013,8 @@ class MyStack() {
}
```
+### C#:
-C#:
```csharp
public class MyStack {
Queue
+
diff --git a/problems/0232.用栈实现队列.md b/problems/0232.用栈实现队列.md
index 4a57ee96..c510fc12 100644
--- a/problems/0232.用栈实现队列.md
+++ b/problems/0232.用栈实现队列.md
@@ -36,11 +36,12 @@ queue.empty(); // 返回 false
* 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
* 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。
+## 算法公开课
+
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[栈的基本操作! | LeetCode:232.用栈实现队列](https://www.bilibili.com/video/BV1nY4y1w7VC),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+
## 思路
-《代码随想录》算法公开课:[栈的基本操作! | LeetCode:232.用栈实现队列](https://www.bilibili.com/video/BV1nY4y1w7VC),相信结合视频再看本篇题解,更有助于大家对栈和队列的理解。
-
-
这是一道模拟题,不涉及到具体算法,考察的就是对栈和队列的掌握程度。
使用栈来模式队列的行为,如果仅仅用一个栈,是一定不行的,所以需要两个栈**一个输入栈,一个输出栈**,这里要注意输入栈和输出栈的关系。
@@ -132,7 +133,7 @@ public:
## 其他语言版本
-Java:
+### Java:
```java
class MyQueue {
@@ -179,8 +180,8 @@ class MyQueue {
```
+### Python:
-Python:
```python
class MyQueue:
@@ -231,8 +232,8 @@ class MyQueue:
```
+### Go:
-Go:
```Go
type MyQueue struct {
stackIn []int //输入栈
@@ -283,7 +284,7 @@ func (this *MyQueue) Empty() bool {
}
```
- javaScript:
+### JavaScript:
```js
// 使用两个数组的栈方法(push, pop) 实现队列
@@ -338,7 +339,7 @@ MyQueue.prototype.empty = function() {
};
```
-TypeScript:
+### TypeScript:
```typescript
class MyQueue {
@@ -374,7 +375,7 @@ class MyQueue {
}
```
-Swift:
+### Swift:
```swift
class MyQueue {
@@ -413,7 +414,8 @@ class MyQueue {
}
```
-C:
+### C:
+
```C
/*
1.两个type为int的数组(栈),大小为100
@@ -490,8 +492,8 @@ void myQueueFree(MyQueue* obj) {
}
```
+### C#:
-C#:
```csharp
public class MyQueue {
Stack
-
diff --git a/problems/0235.二叉搜索树的最近公共祖先.md b/problems/0235.二叉搜索树的最近公共祖先.md
index 9777bb0b..2b8af060 100644
--- a/problems/0235.二叉搜索树的最近公共祖先.md
+++ b/problems/0235.二叉搜索树的最近公共祖先.md
@@ -36,11 +36,11 @@
* 所有节点的值都是唯一的。
* p、q 为不同节点且均存在于给定的二叉搜索树中。
-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[二叉搜索树找祖先就有点不一样了!| 235. 二叉搜索树的最近公共祖先](https://www.bilibili.com/video/BV1Zt4y1F7ww?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[二叉搜索树找祖先就有点不一样了!| 235. 二叉搜索树的最近公共祖先](https://www.bilibili.com/video/BV1Zt4y1F7ww?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
-# 思路
+## 思路
做过[二叉树:公共祖先问题](https://programmercarl.com/0236.二叉树的最近公共祖先.html)题目的同学应该知道,利用回溯从底向上搜索,遇到一个节点的左子树里有p,右子树里有q,那么当前节点就是最近公共祖先。
@@ -71,7 +71,7 @@
可以看出直接按照指定的方向,就可以找到节点8,为最近公共祖先,而且不需要遍历整棵树,找到结果直接返回!
-## 递归法
+### 递归法
递归三部曲如下:
@@ -203,7 +203,7 @@ public:
};
```
-## 迭代法
+### 迭代法
对于二叉搜索树的迭代法,大家应该在[二叉树:二叉搜索树登场!](https://programmercarl.com/0700.二叉搜索树中的搜索.html)就了解了。
@@ -229,7 +229,7 @@ public:
灵魂拷问:是不是又被简单的迭代法感动到痛哭流涕?
-# 总结
+## 总结
对于二叉搜索树的最近祖先问题,其实要比[普通二叉树公共祖先问题](https://programmercarl.com/0236.二叉树的最近公共祖先.html)简单的多。
@@ -238,10 +238,10 @@ public:
最后给出了对应的迭代法,二叉搜索树的迭代法甚至比递归更容易理解,也是因为其有序性(自带方向性),按照目标区间找就行了。
-# 其他语言版本
+## 其他语言版本
-## Java
+### Java
递归法:
```java
@@ -273,7 +273,7 @@ class Solution {
```
-## Python
+### Python
递归法(版本一)
```python
@@ -326,7 +326,7 @@ class Solution:
```
-## Go
+### Go
递归法:
```go
@@ -350,7 +350,7 @@ func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
```
-## JavaScript
+### JavaScript
递归法:
```javascript
@@ -391,7 +391,7 @@ var lowestCommonAncestor = function(root, p, q) {
};
```
-## TypeScript
+### TypeScript
> 递归法:
@@ -422,7 +422,7 @@ function lowestCommonAncestor(root: TreeNode | null, p: TreeNode | null, q: Tree
};
```
-## Scala
+### Scala
递归:
@@ -453,7 +453,7 @@ object Solution {
}
```
-## rust
+### Rust
递归:
@@ -519,3 +519,4 @@ impl Solution {
+
diff --git a/problems/0236.二叉树的最近公共祖先.md b/problems/0236.二叉树的最近公共祖先.md
index 0ebd5566..9db7409e 100644
--- a/problems/0236.二叉树的最近公共祖先.md
+++ b/problems/0236.二叉树的最近公共祖先.md
@@ -34,12 +34,12 @@
* 所有节点的值都是唯一的。
* p、q 为不同节点且均存在于给定的二叉树中。
-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[自底向上查找,有点难度! | LeetCode:236. 二叉树的最近公共祖先](https://www.bilibili.com/video/BV1jd4y1B7E2),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[自底向上查找,有点难度! | LeetCode:236. 二叉树的最近公共祖先](https://www.bilibili.com/video/BV1jd4y1B7E2),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
-# 思路
+## 思路
遇到这个题目首先想的是要是能自底向上查找就好了,这样就可以找到公共祖先了。
@@ -226,7 +226,7 @@ public:
};
```
-# 总结
+## 总结
这道题目刷过的同学未必真正了解这里面回溯的过程,以及结果是如何一层一层传上去的。
@@ -243,10 +243,10 @@ public:
本题没有给出迭代法,因为迭代法不适合模拟回溯的过程。理解递归的解法就够了。
-# 其他语言版本
+## 其他语言版本
-## Java
+### Java
```Java
class Solution {
@@ -273,7 +273,7 @@ class Solution {
```
-## Python
+### Python
递归法(版本一)
```python
class Solution:
@@ -312,7 +312,7 @@ class Solution:
return left
```
-## Go
+### Go
```Go
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
@@ -343,7 +343,7 @@ func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
}
```
-## JavaScript
+### JavaScript
```javascript
var lowestCommonAncestor = function(root, p, q) {
@@ -370,7 +370,7 @@ var lowestCommonAncestor = function(root, p, q) {
};
```
-## TypeScript
+### TypeScript
```typescript
function lowestCommonAncestor(root: TreeNode | null, p: TreeNode | null, q: TreeNode | null): TreeNode | null {
@@ -384,7 +384,7 @@ function lowestCommonAncestor(root: TreeNode | null, p: TreeNode | null, q: Tree
};
```
-## Scala
+### Scala
```scala
object Solution {
@@ -404,7 +404,7 @@ object Solution {
}
```
-## rust
+### Rust
```rust
impl Solution {
@@ -436,3 +436,4 @@ impl Solution {
+
diff --git a/problems/0239.滑动窗口最大值.md b/problems/0239.滑动窗口最大值.md
index f1c4b76c..6f420479 100644
--- a/problems/0239.滑动窗口最大值.md
+++ b/problems/0239.滑动窗口最大值.md
@@ -28,11 +28,11 @@
* -10^4 <= nums[i] <= 10^4
* 1 <= k <= nums.length
+## 算法公开课
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[单调队列正式登场!| LeetCode:239. 滑动窗口最大值](https://www.bilibili.com/video/BV1XS4y1p7qj),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
-# 思路
-
-《代码随想录》算法视频公开课:[单调队列正式登场!| LeetCode:239. 滑动窗口最大值](https://www.bilibili.com/video/BV1XS4y1p7qj),相信结合视频在看本篇题解,更有助于大家对本题的理解。
+## 思路
这是使用单调队列的经典题目。
@@ -196,7 +196,7 @@ public:
空间复杂度因为我们定义一个辅助队列,所以是O(k)。
-# 扩展
+## 扩展
大家貌似对单调队列 都有一些疑惑,首先要明确的是,题解中单调队列里的pop和push接口,仅适用于本题哈。单调队列不是一成不变的,而是不同场景不同写法,总之要保证队列里单调递减或递增的原则,所以叫做单调队列。 不要以为本题中的单调队列实现就是固定的写法哈。
@@ -204,10 +204,10 @@ public:
-# 其他语言版本
+## 其他语言版本
+### Java:
-Java:
```Java
//解法一
//自定义数组
@@ -298,7 +298,8 @@ class Solution {
}
```
-Python:
+### Python:
+
```python
from collections import deque
@@ -338,8 +339,7 @@ class Solution:
return result
```
-
-Go:
+### Go:
```go
// 封装单调队列的方式解题
@@ -401,7 +401,8 @@ func maxSlidingWindow(nums []int, k int) []int {
}
```
-Javascript:
+### Javascript:
+
```javascript
/**
* @param {number[]} nums
@@ -449,7 +450,7 @@ var maxSlidingWindow = function (nums, k) {
};
```
-TypeScript:
+### TypeScript:
```typescript
function maxSlidingWindow(nums: number[], k: number): number[] {
@@ -497,7 +498,9 @@ function maxSlidingWindow(nums: number[], k: number): number[] {
};
```
-Swift:
+### Swift:
+
+解法一:
```Swift
/// 双向链表
@@ -638,7 +641,8 @@ func maxSlidingWindow(_ nums: [Int], _ k: Int) -> [Int] {
return result
}
```
-Scala:
+### Scala:
+
```scala
import scala.collection.mutable.ArrayBuffer
object Solution {
@@ -686,8 +690,8 @@ class MyQueue {
}
```
+### PHP:
-PHP:
```php
class Solution {
/**
@@ -764,7 +768,8 @@ class MyQueue{
}
```
-C#:
+### C#:
+
```csharp
class myDequeue{
private LinkedList
+
diff --git a/problems/0257.二叉树的所有路径.md b/problems/0257.二叉树的所有路径.md
index 06153507..44c0fd85 100644
--- a/problems/0257.二叉树的所有路径.md
+++ b/problems/0257.二叉树的所有路径.md
@@ -18,9 +18,11 @@
示例:

-# 思路
+## 算法公开课
-**《代码随想录》算法视频公开课:[递归中带着回溯,你感受到了没?| LeetCode:257. 二叉树的所有路径](https://www.bilibili.com/video/BV1ZG411G7Dh),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)::[递归中带着回溯,你感受到了没?| LeetCode:257. 二叉树的所有路径](https://www.bilibili.com/video/BV1ZG411G7Dh),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+
+## 思路
这道题目要求从根节点到叶子的路径,所以需要前序遍历,这样才方便让父节点指向孩子节点,找到对应的路径。
@@ -32,7 +34,7 @@
我们先使用递归的方式,来做前序遍历。**要知道递归和回溯就是一家的,本题也需要回溯。**
-## 递归
+### 递归
1. 递归函数参数以及返回值
@@ -305,7 +307,7 @@ public:
**综合以上,第二种递归的代码虽然精简但把很多重要的点隐藏在了代码细节里,第一种递归写法虽然代码多一些,但是把每一个逻辑处理都完整的展现出来了。**
-## 拓展
+### 拓展
这里讲解本题解的写法逻辑以及一些更具体的细节,下面的讲解中,涉及到C++语法特性,如果不是C++的录友,就可以不看了,避免越看越晕。
@@ -328,7 +330,7 @@ public:
所以,第一个代码版本中,我才使用 vector 类型的path,这样方便给大家演示代码中回溯的操作。 vector类型的path,不管 每次 路径收集的数字是几位数,总之一定是int,所以就一次 pop_back就可以。
-## 迭代法
+### 迭代法
至于非递归的方式,我们可以依然可以使用前序遍历的迭代方式来模拟遍历路径的过程,对该迭代方式不了解的同学,可以看文章[二叉树:听说递归能做的,栈也能做!](https://programmercarl.com/二叉树的迭代遍历.html)和[二叉树:前中后序迭代方式统一写法](https://programmercarl.com/二叉树的统一迭代法.html)。
@@ -368,7 +370,7 @@ public:
```
当然,使用java的同学,可以直接定义一个成员变量为object的栈`Stack
-
diff --git a/problems/0383.赎金信.md b/problems/0383.赎金信.md
index e74cdf71..c15d1ac1 100644
--- a/problems/0383.赎金信.md
+++ b/problems/0383.赎金信.md
@@ -34,7 +34,7 @@ canConstruct("aa", "aab") -> true
* 第二点 “你可以假设两个字符串均只含有小写字母。” *说明只有小写字母*,这一点很重要
-## 暴力解法
+### 暴力解法
那么第一个思路其实就是暴力枚举了,两层for循环,不断去寻找,代码如下:
@@ -66,7 +66,7 @@ public:
这里时间复杂度是比较高的,而且里面还有一个字符串删除也就是erase的操作,也是费时的,当然这段代码也可以过这道题。
-## 哈希解法
+### 哈希解法
因为题目所只有小写字母,那可以采用空间换取时间的哈希策略, 用一个长度为26的数组还记录magazine里字母出现的次数。
@@ -88,7 +88,7 @@ public:
return false;
}
for (int i = 0; i < magazine.length(); i++) {
- // 通过recode数据记录 magazine里各个字符出现次数
+ // 通过record数据记录 magazine里各个字符出现次数
record[magazine[i]-'a'] ++;
}
for (int j = 0; j < ransomNote.length(); j++) {
@@ -112,8 +112,8 @@ public:
## 其他语言版本
+### Java:
-Java:
```Java
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
@@ -146,8 +146,9 @@ class Solution {
```
-Python:
+### Python:
(版本一)使用数组
+
```python
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
@@ -213,12 +214,12 @@ class Solution:
return all(ransomNote.count(c) <= magazine.count(c) for c in set(ransomNote))
```
-Go:
+### Go:
```go
func canConstruct(ransomNote string, magazine string) bool {
record := make([]int, 26)
- for _, v := range magazine { // 通过recode数据记录 magazine里各个字符出现次数
+ for _, v := range magazine { // 通过record数据记录 magazine里各个字符出现次数
record[v-'a']++
}
for _, v := range ransomNote { // 遍历ransomNote,在record里对应的字符个数做--操作
@@ -231,7 +232,7 @@ func canConstruct(ransomNote string, magazine string) bool {
}
```
-javaScript:
+### JavaScript:
```js
/**
@@ -254,7 +255,7 @@ var canConstruct = function(ransomNote, magazine) {
};
```
-TypeScript:
+### TypeScript:
```typescript
function canConstruct(ransomNote: string, magazine: string): boolean {
@@ -275,8 +276,8 @@ function canConstruct(ransomNote: string, magazine: string): boolean {
};
```
+### PHP:
-PHP:
```php
class Solution {
/**
@@ -301,7 +302,8 @@ class Solution {
}
```
-Swift:
+### Swift:
+
```swift
func canConstruct(_ ransomNote: String, _ magazine: String) -> Bool {
var record = Array(repeating: 0, count: 26);
@@ -324,7 +326,8 @@ func canConstruct(_ ransomNote: String, _ magazine: String) -> Bool {
}
```
-Rust:
+### Rust:
+
```rust
impl Solution {
pub fn can_construct(ransom_note: String, magazine: String) -> bool {
@@ -347,7 +350,7 @@ impl Solution {
}
```
-Scala:
+### Scala:
版本一: 使用数组作为哈希表
```scala
@@ -411,8 +414,8 @@ object Solution {
}
```
+### C#:
-C#:
```csharp
public bool CanConstruct(string ransomNote, string magazine) {
if(ransomNote.Length > magazine.Length) return false;
@@ -434,3 +437,4 @@ public bool CanConstruct(string ransomNote, string magazine) {
+
diff --git a/problems/0404.左叶子之和.md b/problems/0404.左叶子之和.md
index aa2868df..c1ad602d 100644
--- a/problems/0404.左叶子之和.md
+++ b/problems/0404.左叶子之和.md
@@ -16,9 +16,9 @@

-## 视频讲解
+## 算法公开课
-**《代码随想录》算法视频公开课:[二叉树的题目中,总有一些规则让你找不到北 | LeetCode:404.左叶子之和](https://www.bilibili.com/video/BV1GY4y1K7z8),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)::[二叉树的题目中,总有一些规则让你找不到北 | LeetCode:404.左叶子之和](https://www.bilibili.com/video/BV1GY4y1K7z8),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -48,7 +48,7 @@ if (node->left != NULL && node->left->left == NULL && node->left->right == NULL)
}
```
-## 递归法
+### 递归法
递归的遍历顺序为后序遍历(左右中),是因为要通过递归函数的返回值来累加求取左叶子数值之和。
@@ -131,11 +131,11 @@ public:
return leftValue + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
}
};
-```
+```
精简之后的代码其实看不出来用的是什么遍历方式了,对于算法初学者以上根据第一个版本来学习。
-## 迭代法
+### 迭代法
本题迭代法使用前中后序都是可以的,只要把左叶子节点统计出来,就可以了,那么参考文章 [二叉树:听说递归能做的,栈也能做!](https://programmercarl.com/二叉树的迭代遍历.html)和[二叉树:迭代法统一写法](https://programmercarl.com/二叉树的统一迭代法.html)中的写法,可以写出一个前序遍历的迭代法。
@@ -177,7 +177,7 @@ public:
## 其他语言版本
-### Java
+### Java:
**递归**
@@ -246,7 +246,7 @@ class Solution {
```
-### Python
+### Python:
递归
```python
# Definition for a binary tree node.
@@ -316,7 +316,7 @@ class Solution:
```
-### Go
+### Go:
**递归法**
@@ -368,7 +368,7 @@ func sumOfLeftLeaves(root *TreeNode) int {
```
-### JavaScript
+### JavaScript:
**递归法**
@@ -417,7 +417,7 @@ var sumOfLeftLeaves = function(root) {
};
```
-### TypeScript
+### TypeScript:
> 递归法
@@ -462,7 +462,7 @@ function sumOfLeftLeaves(root: TreeNode | null): number {
};
```
-### Swift
+### Swift:
**递归法**
```swift
@@ -511,7 +511,7 @@ func sumOfLeftLeaves(_ root: TreeNode?) -> Int {
}
```
-### C
+### C:
递归法:
```c
int sumOfLeftLeaves(struct TreeNode* root){
@@ -561,7 +561,7 @@ int sumOfLeftLeaves(struct TreeNode* root){
}
```
-### Scala
+### Scala:
**递归:**
```scala
@@ -600,7 +600,7 @@ object Solution {
}
```
-### Rust
+### Rust:
**递归**
@@ -656,3 +656,4 @@ impl Solution {
+
diff --git a/problems/0450.删除二叉搜索树中的节点.md b/problems/0450.删除二叉搜索树中的节点.md
index e617cc69..18e5cb4c 100644
--- a/problems/0450.删除二叉搜索树中的节点.md
+++ b/problems/0450.删除二叉搜索树中的节点.md
@@ -24,15 +24,15 @@

-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[调整二叉树的结构最难!| LeetCode:450.删除二叉搜索树中的节点](https://www.bilibili.com/video/BV1tP41177us?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[调整二叉树的结构最难!| LeetCode:450.删除二叉搜索树中的节点](https://www.bilibili.com/video/BV1tP41177us?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
-# 思路
+## 思路
搜索树的节点删除要比节点增加复杂的多,有很多情况需要考虑,做好心理准备。
-## 递归
+### 递归
递归三部曲:
@@ -161,7 +161,7 @@ public:
};
```
-## 普通二叉树的删除方式
+### 普通二叉树的删除方式
这里我在介绍一种通用的删除,普通二叉树的删除方式(没有使用搜索树的特性,遍历整棵树),用交换值的操作来删除目标节点。
@@ -198,7 +198,7 @@ public:
这个代码是简短一些,思路也巧妙,但是不太好想,实操性不强,推荐第一种写法!
-## 迭代法
+### 迭代法
删除节点的迭代法还是复杂一些的,但其本质我在递归法里都介绍了,最关键就是删除节点的操作(动画模拟的过程)
@@ -246,7 +246,7 @@ public:
};
```
-# 总结
+## 总结
读完本篇,大家会发现二叉搜索树删除节点比增加节点复杂的多。
@@ -264,10 +264,10 @@ public:
迭代法其实不太容易写出来,所以如果是初学者的话,彻底掌握第一种递归写法就够了。
-# 其他语言版本
+## 其他语言版本
-## Java
+### Java
```java
// 解法1(最好理解的版本)
class Solution {
@@ -375,7 +375,8 @@ class Solution {
```
-## Python
+### Python
+
递归法(版本一)
```python
class Solution:
@@ -463,7 +464,7 @@ class Solution:
return root
```
-## Go
+### Go
```Go
// 递归版本
func deleteNode(root *TreeNode, key int) *TreeNode {
@@ -549,7 +550,7 @@ func deleteNode(root *TreeNode, key int) *TreeNode {
}
```
-## JavaScript
+### JavaScript
递归
@@ -640,7 +641,7 @@ var deleteNode = function (root, key) {
}
```
-## TypeScript
+### TypeScript
> 递归法:
@@ -704,7 +705,7 @@ function deleteNode(root: TreeNode | null, key: number): TreeNode | null {
};
```
-## Scala
+### Scala
```scala
object Solution {
@@ -734,7 +735,7 @@ object Solution {
}
```
-## rust
+### Rust
```rust
impl Solution {
@@ -772,3 +773,4 @@ impl Solution {
+
diff --git a/problems/0454.四数相加II.md b/problems/0454.四数相加II.md
index 4a16d4f4..90c37334 100644
--- a/problems/0454.四数相加II.md
+++ b/problems/0454.四数相加II.md
@@ -34,10 +34,12 @@
1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0
+## 算法公开课
-# 思路
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[学透哈希表,map使用有技巧!LeetCode:454.四数相加II](https://www.bilibili.com/video/BV1Md4y1Q7Yh),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
-本题视频讲解:[学透哈希表,map使用有技巧!LeetCode:454.四数相加II](https://www.bilibili.com/video/BV1Md4y1Q7Yh),结合视频在看本题解,事半功倍。
+
+## 思路
本题咋眼一看好像和[0015.三数之和](https://programmercarl.com/0015.三数之和.html),[0018.四数之和](https://programmercarl.com/0018.四数之和.html)差不多,其实差很多。
@@ -92,8 +94,8 @@ public:
## 其他语言版本
+### Java:
-Java:
```Java
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
@@ -117,8 +119,9 @@ class Solution {
}
```
-Python:
+### Python:
(版本一) 使用字典
+
```python
class Solution(object):
def fourSumCount(self, nums1, nums2, nums3, nums4):
@@ -179,7 +182,7 @@ class Solution:
return cnt
```
-Go:
+### Go:
```go
func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int {
@@ -201,7 +204,7 @@ func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int {
}
```
-javaScript:
+### JavaScript:
```js
/**
@@ -233,7 +236,7 @@ var fourSumCount = function(nums1, nums2, nums3, nums4) {
};
```
-TypeScript:
+### TypeScript:
```typescript
function fourSumCount(nums1: number[], nums2: number[], nums3: number[], nums4: number[]): number {
@@ -258,7 +261,7 @@ function fourSumCount(nums1: number[], nums2: number[], nums3: number[], nums4:
};
```
-PHP:
+### PHP:
```php
class Solution {
@@ -291,8 +294,8 @@ class Solution {
}
```
+### Swift:
-Swift:
```swift
func fourSumCount(_ nums1: [Int], _ nums2: [Int], _ nums3: [Int], _ nums4: [Int]) -> Int {
// ab和: ab和出现次数
@@ -316,7 +319,8 @@ func fourSumCount(_ nums1: [Int], _ nums2: [Int], _ nums3: [Int], _ nums4: [Int]
}
```
-Rust:
+### Rust:
+
```rust
use std::collections::HashMap;
impl Solution {
@@ -342,8 +346,8 @@ impl Solution {
}
```
+### Scala:
-Scala:
```scala
object Solution {
// 导包
@@ -380,7 +384,8 @@ object Solution {
}
```
-C#:
+### C#:
+
```csharp
public int FourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
Dictionary
+
diff --git a/problems/0459.重复的子字符串.md b/problems/0459.重复的子字符串.md
index 5d56ad18..f99102ab 100644
--- a/problems/0459.重复的子字符串.md
+++ b/problems/0459.重复的子字符串.md
@@ -5,8 +5,6 @@
-
diff --git a/problems/0494.目标和.md b/problems/0494.目标和.md
index 32931e6b..1902d5ed 100644
--- a/problems/0494.目标和.md
+++ b/problems/0494.目标和.md
@@ -292,6 +292,85 @@ class Solution {
}
```
+易于理解的二维数组版本:
+```java
+class Solution {
+ public int findTargetSumWays(int[] nums, int target) {
+
+ // 01背包应用之“有多少种不同的填满背包最大容量的方法“
+ // 易于理解的二维数组解法及详细注释
+
+ int sum = 0;
+ for(int i = 0; i < nums.length; i++) {
+ sum += nums[i];
+ }
+
+ // 注意nums[i] >= 0的题目条件,意味着sum也是所有nums[i]的绝对值之和
+ // 这里保证了sum + target一定是大于等于零的,也就是left大于等于零(毕竟我们定义left大于right)
+ if(sum < Math.abs(target)){
+ return 0;
+ }
+
+ // 利用二元一次方程组将left用target和sum表示出来(替换掉right组合),详见代码随想录对此题的分析
+ // 如果所求的left数组和为小数,则作为整数数组的nums里的任何元素自然是没有办法凑出这个小数的
+ if((sum + target) % 2 != 0) {
+ return 0;
+ }
+
+ int left = (sum + target) / 2;
+
+ // dp[i][j]:遍历到数组第i个数时, left为j时的能装满背包的方法总数
+ int[][] dp = new int[nums.length][left + 1];
+
+ // 初始化最上行(dp[0][j]),当nums[0] == j时(注意nums[0]和j都一定是大于等于零的,因此不需要判断等于-j时的情况),有唯一一种取法可取到j,dp[0][j]此时等于1
+ // 其他情况dp[0][j] = 0
+ // java整数数组默认初始值为0
+ for(int j = 0; j <= left; j++) {
+ if(nums[0] == j) {
+ dp[0][j] = 1;
+ }
+ }
+
+ // 初始化最左列(dp[i][0])
+ // 当从nums数组的索引0到i的部分有n个0时(n > 0),每个0可以取+/-,因此有2的n次方中可以取到j = 0的方案
+ // n = 0说明当前遍历到的数组部分没有0全为正数,因此只有一种方案可以取到j = 0(就是所有数都不取)
+ int numZeros = 0;
+ for(int i = 0; i < nums.length; i++) {
+ if(nums[i] == 0) {
+ numZeros++;
+ }
+ dp[i][0] = (int) Math.pow(2, numZeros);
+
+ }
+
+ // 递推公式分析:
+ // 当nums[i] > j时,这时候nums[i]一定不能取,所以是dp[i - 1][j]种方案数
+ // nums[i] <= j时,num[i]可取可不取,因此方案数是dp[i - 1][j] + dp[i - 1][j - nums[i]]
+ // 由递推公式可知,先遍历i或j都可
+ for(int i = 1; i < nums.length; i++) {
+ for(int j = 1; j <= left; j++) {
+ if(nums[i] > j) {
+ dp[i][j] = dp[i - 1][j];
+ } else {
+ dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i]];
+ }
+ }
+ }
+
+ // 打印dp数组
+ // for(int i = 0; i < nums.length; i++) {
+ // for(int j = 0; j <= left; j++) {
+ // System.out.print(dp[i][j] + " ");
+ // }
+ // System.out.println("");
+ // }
+
+ return dp[nums.length - 1][left];
+
+ }
+}
+```
+
### Python
回溯版
```python
diff --git a/problems/0501.二叉搜索树中的众数.md b/problems/0501.二叉搜索树中的众数.md
index 1da32343..efbabc4a 100644
--- a/problems/0501.二叉搜索树中的众数.md
+++ b/problems/0501.二叉搜索树中的众数.md
@@ -33,20 +33,20 @@
进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)
-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[不仅双指针,还有代码技巧可以惊艳到你! | LeetCode:501.二叉搜索树中的众数](https://www.bilibili.com/video/BV1fD4y117gp),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[不仅双指针,还有代码技巧可以惊艳到你! | LeetCode:501.二叉搜索树中的众数](https://www.bilibili.com/video/BV1fD4y117gp),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
-# 思路
+## 思路
这道题目呢,递归法我从两个维度来讲。
首先如果不是二叉搜索树的话,应该怎么解题,是二叉搜索树,又应该如何解题,两种方式做一个比较,可以加深大家对二叉树的理解。
-## 递归法
+### 递归法
-### 如果不是二叉搜索树
+#### 如果不是二叉搜索树
如果不是二叉搜索树,最直观的方法一定是把这个树都遍历了,用map统计频率,把频率排个序,最后取前面高频的元素的集合。
@@ -140,7 +140,7 @@ public:
**所以如果本题没有说是二叉搜索树的话,那么就按照上面的思路写!**
-### 是二叉搜索树
+#### 是二叉搜索树
**既然是搜索树,它中序遍历就是有序的**。
@@ -271,7 +271,7 @@ public:
```
-## 迭代法
+### 迭代法
只要把中序遍历转成迭代,中间节点的处理逻辑完全一样。
@@ -326,7 +326,7 @@ public:
};
```
-# 总结
+## 总结
本题在递归法中,我给出了如果是普通二叉树,应该怎么求众数。
@@ -345,10 +345,10 @@ public:
> **需要强调的是 leetcode上的耗时统计是非常不准确的,看个大概就行,一样的代码耗时可以差百分之50以上**,所以leetcode的耗时统计别太当回事,知道理论上的效率优劣就行了。
-# 其他语言版本
+## 其他语言版本
-## Java
+### Java
暴力法
@@ -472,7 +472,7 @@ class Solution {
}
}
```
-統一迭代法
+统一迭代法
```Java
class Solution {
public int[] findMode(TreeNode root) {
@@ -526,7 +526,7 @@ class Solution {
```
-## Python
+### Python
递归法(版本一)利用字典
@@ -640,7 +640,7 @@ class Solution:
return result
```
-## Go
+### Go
计数法,不使用额外空间,利用二叉树性质,中序遍历
```go
@@ -676,7 +676,7 @@ func findMode(root *TreeNode) []int {
}
```
-## JavaScript
+### JavaScript
使用额外空间map的方法
```javascript
@@ -753,7 +753,7 @@ var findMode = function(root) {
};
```
-## TypeScript
+### TypeScript
> 辅助Map法
@@ -852,7 +852,7 @@ function findMode(root: TreeNode | null): number[] {
};
```
-## Scala
+### Scala
暴力:
```scala
@@ -923,7 +923,7 @@ object Solution {
}
```
-## rust
+### Rust
递归:
@@ -1015,3 +1015,4 @@ pub fn find_mode(root: Option
+
diff --git a/problems/0513.找树左下角的值.md b/problems/0513.找树左下角的值.md
index 743b0df9..7ef934cc 100644
--- a/problems/0513.找树左下角的值.md
+++ b/problems/0513.找树左下角的值.md
@@ -20,9 +20,9 @@

-## 视频讲解
+## 算法公开课
-**《代码随想录》算法视频公开课:[怎么找二叉树的左下角? 递归中又带回溯了,怎么办?| LeetCode:513.找二叉树左下角的值](https://www.bilibili.com/video/BV1424y1Z7pn),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[怎么找二叉树的左下角? 递归中又带回溯了,怎么办?| LeetCode:513.找二叉树左下角的值](https://www.bilibili.com/video/BV1424y1Z7pn),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -614,7 +614,7 @@ object Solution {
}
```
-### rust
+### Rust
**层序遍历**
@@ -689,3 +689,4 @@ impl Solution {
+
diff --git a/problems/0530.二叉搜索树的最小绝对差.md b/problems/0530.二叉搜索树的最小绝对差.md
index 3e4391d6..56911858 100644
--- a/problems/0530.二叉搜索树的最小绝对差.md
+++ b/problems/0530.二叉搜索树的最小绝对差.md
@@ -19,12 +19,12 @@
提示:树中至少有 2 个节点。
-# 视频讲解
+## 算法公开课
-**《代码随想录》算法视频公开课:[二叉搜索树中,需要掌握如何双指针遍历!| LeetCode:530.二叉搜索树的最小绝对差](https://www.bilibili.com/video/BV1DD4y11779),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[二叉搜索树中,需要掌握如何双指针遍历!| LeetCode:530.二叉搜索树的最小绝对差](https://www.bilibili.com/video/BV1DD4y11779),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
-# 思路
+## 思路
题目中要求在二叉搜索树上任意两节点的差的绝对值的最小值。
@@ -32,7 +32,7 @@
遇到在二叉搜索树上求什么最值啊,差值之类的,就把它想成在一个有序数组上求最值,求差值,这样就简单多了。
-## 递归
+### 递归
那么二叉搜索树采用中序遍历,其实就是一个有序数组。
@@ -102,7 +102,7 @@ public:
是不是看上去也并不复杂!
-## 迭代
+### 迭代
看过这两篇[二叉树:听说递归能做的,栈也能做!](https://programmercarl.com/二叉树的迭代遍历.html),[二叉树:前中后序迭代方式的写法就不能统一一下么?](https://programmercarl.com/二叉树的统一迭代法.html)文章之后,不难写出两种中序遍历的迭代法。
@@ -135,7 +135,7 @@ public:
};
```
-# 总结
+## 总结
**遇到在二叉搜索树上求什么最值,求差值之类的,都要思考一下二叉搜索树可是有序的,要利用好这一特点。**
@@ -145,10 +145,10 @@ public:
-# 其他语言版本
+## 其他语言版本
-## Java
+### Java
递归
```java
@@ -235,7 +235,7 @@ class Solution {
}
}
```
-## Python
+### Python
递归法(版本一)利用中序递增,结合数组
```python
@@ -313,7 +313,7 @@ class Solution:
```
-## Go:
+### Go
中序遍历,然后计算最小差值
```go
@@ -340,7 +340,7 @@ func getMinimumDifference(root *TreeNode) int {
}
```
-## JavaScript
+### JavaScript
递归 先转换为有序数组
```javascript
/**
@@ -415,7 +415,7 @@ var getMinimumDifference = function(root) {
}
```
-## TypeScript
+### TypeScript
> 辅助数组解决
@@ -482,7 +482,7 @@ function getMinimumDifference(root: TreeNode | null): number {
};
```
-## Scala
+### Scala
构建二叉树的有序数组:
@@ -561,7 +561,7 @@ object Solution {
}
```
-## rust
+### Rust
构建二叉树的有序数组:
@@ -652,3 +652,4 @@ impl Solution {
+
diff --git a/problems/0538.把二叉搜索树转换为累加树.md b/problems/0538.把二叉搜索树转换为累加树.md
index 781763a4..c403c98f 100644
--- a/problems/0538.把二叉搜索树转换为累加树.md
+++ b/problems/0538.把二叉搜索树转换为累加树.md
@@ -44,11 +44,11 @@
* 树中的所有值 互不相同 。
* 给定的树为二叉搜索树。
-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[普大喜奔!二叉树章节已全部更完啦!| LeetCode:538.把二叉搜索树转换为累加树](https://www.bilibili.com/video/BV1d44y1f7wP?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[普大喜奔!二叉树章节已全部更完啦!| LeetCode:538.把二叉搜索树转换为累加树](https://www.bilibili.com/video/BV1d44y1f7wP?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
-# 思路
+## 思路
一看到累加树,相信很多小伙伴都会疑惑:如何累加?遇到一个节点,然后再遍历其他节点累加?怎么一想这么麻烦呢。
@@ -64,7 +64,7 @@
那么知道如何遍历这个二叉树,也就迎刃而解了,**从树中可以看出累加的顺序是右中左,所以我们需要反中序遍历这个二叉树,然后顺序累加就可以了**。
-## 递归
+### 递归
遍历顺序如图所示:
@@ -131,7 +131,7 @@ public:
};
```
-## 迭代法
+### 迭代法
迭代法其实就是中序模板题了,在[二叉树:前中后序迭代法](https://programmercarl.com/二叉树的迭代遍历.html)和[二叉树:前中后序统一方式迭代法](https://programmercarl.com/二叉树的统一迭代法.html)可以选一种自己习惯的写法。
@@ -166,17 +166,17 @@ public:
};
```
-# 总结
+## 总结
经历了前面各种二叉树增删改查的洗礼之后,这道题目应该比较简单了。
**好了,二叉树已经接近尾声了,接下来就是要对二叉树来一个大总结了**。
-# 其他语言版本
+## 其他语言版本
-## Java
+### Java
**递归**
```Java
@@ -237,7 +237,7 @@ class Solution {
}
```
-## Python
+### Python
递归法(版本一)
```python
# Definition for a binary tree node.
@@ -318,7 +318,7 @@ class Solution:
self.traversal(root)
return root
-```
+```
迭代法(版本二)
```python
class Solution:
@@ -338,9 +338,9 @@ class Solution:
pre = cur.val
cur =cur.left
return root
-```
+```
-## Go
+### Go
弄一个sum暂存其和值
```go
@@ -362,7 +362,7 @@ func traversal(cur *TreeNode) {
}
```
-## JavaScript
+### JavaScript
递归
```javascript
@@ -401,7 +401,7 @@ var convertBST = function (root) {
};
```
-##C
+### C
递归
```c
@@ -422,7 +422,7 @@ struct TreeNode* convertBST(struct TreeNode* root){
}
```
-## TypeScript
+### TypeScript
> 递归法
@@ -462,7 +462,7 @@ function convertBST(root: TreeNode | null): TreeNode | null {
};
```
-## Scala
+### Scala
```scala
object Solution {
@@ -481,7 +481,7 @@ object Solution {
}
```
-## rust
+### Rust
递归:
@@ -535,3 +535,4 @@ impl Solution {
+
diff --git a/problems/0541.反转字符串II.md b/problems/0541.反转字符串II.md
index 179395b3..80e662f9 100644
--- a/problems/0541.反转字符串II.md
+++ b/problems/0541.反转字符串II.md
@@ -23,9 +23,11 @@
输入: s = "abcdefg", k = 2
输出: "bacdfeg"
-# 思路
+## 算法公开课
-针对本题,我录制了视频讲解:[字符串操作进阶! | LeetCode:541. 反转字符串II](https://www.bilibili.com/video/BV1dT411j7NN),结合本题解一起看,事半功倍!
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[字符串操作进阶! | LeetCode:541. 反转字符串II](https://www.bilibili.com/video/BV1dT411j7NN),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+
+## 思路
这道题目其实也是模拟,实现题目中规定的反转规则就可以了。
@@ -42,8 +44,6 @@
那么这里具体反转的逻辑我们要不要使用库函数呢,其实用不用都可以,使用reverse来实现反转也没毛病,毕竟不是解题关键部分。
-# C++代码
-
使用C++库函数reverse的版本如下:
```CPP
@@ -129,7 +129,7 @@ public:
## 其他语言版本
-C:
+### C:
```c
char * reverseStr(char * s, int k){
@@ -152,7 +152,7 @@ char * reverseStr(char * s, int k){
}
```
-Java:
+### Java:
```Java
//解法一
@@ -256,7 +256,8 @@ class Solution {
}
}
```
-Python:
+### Python:
+
```python
class Solution:
def reverseStr(self, s: str, k: int) -> str:
@@ -281,7 +282,7 @@ class Solution:
return ''.join(res)
```
-Python3 (v2):
+### Python3 (v2):
```python
class Solution:
@@ -296,7 +297,7 @@ class Solution:
return s
```
-Go:
+### Go:
```go
func reverseStr(s string, k int) string {
@@ -325,7 +326,7 @@ func reverse(b []byte) {
}
```
-javaScript:
+### JavaScript:
```js
@@ -346,7 +347,7 @@ var reverseStr = function(s, k) {
```
-TypeScript:
+### TypeScript:
```typescript
function reverseStr(s: string, k: number): string {
@@ -368,7 +369,7 @@ function reverseStr(s: string, k: number): string {
};
```
-Swift:
+### Swift:
```swift
func reverseStr(_ s: String, _ k: Int) -> String {
@@ -388,7 +389,8 @@ func reverseStr(_ s: String, _ k: Int) -> String {
}
```
-C#:
+### C#:
+
```csharp
public class Solution
{
@@ -403,7 +405,7 @@ public class Solution
}
}
```
-Scala:
+### Scala:
版本一: (正常解法)
```scala
@@ -469,7 +471,7 @@ object Solution {
}
```
-Rust:
+### Rust:
```Rust
impl Solution {
@@ -503,4 +505,3 @@ impl Solution {
-
diff --git a/problems/0617.合并二叉树.md b/problems/0617.合并二叉树.md
index 18a245c4..44092aae 100644
--- a/problems/0617.合并二叉树.md
+++ b/problems/0617.合并二叉树.md
@@ -19,9 +19,9 @@
注意: 合并必须从两个树的根节点开始。
-# 视频讲解
+# 算法公开课
-**《代码随想录》算法视频公开课:[一起操作两个二叉树?有点懵!| LeetCode:617.合并二叉树](https://www.bilibili.com/video/BV1m14y1Y7JK),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[一起操作两个二叉树?有点懵!| LeetCode:617.合并二叉树](https://www.bilibili.com/video/BV1m14y1Y7JK),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -164,7 +164,7 @@ public:
};
```
-## 迭代法
+### 迭代法
使用迭代法,如何同时处理两棵树呢?
@@ -716,7 +716,7 @@ object Solution {
}
```
-### rust
+### Rust
递归:
@@ -793,4 +793,3 @@ impl Solution {
-
diff --git a/problems/0647.回文子串.md b/problems/0647.回文子串.md
index e172de54..084b9f74 100644
--- a/problems/0647.回文子串.md
+++ b/problems/0647.回文子串.md
@@ -304,7 +304,38 @@ class Solution {
}
}
```
+LeetCode 5. Longest Palindromic Substring(LeetCode 647. 同一題的思路改一下、加一點,就能通過LeetCode 5)
+```java
+class Solution {
+ public String longestPalindrome(String s) {
+ //題目要求要return 最長的回文連續子串,故需要記錄當前最長的連續回文子串長度、最終起點、最終終點。
+ int finalStart = 0;
+ int finalEnd = 0;
+ int finalLen = 0;
+ char[] chars = s.toCharArray();
+ int len = chars.length;
+
+ boolean[][] dp = new boolean[len][len];
+ for (int i = len - 1; i >= 0; i--) {
+ for (int j = i; j < len; j++) {
+ if (chars[i] == chars[j] && (j - i <= 1 || dp[i + 1][j - 1]))
+ dp[i][j] = true;
+ //和LeetCode 647,差別就在這個if statement。
+ //如果當前[i, j]範圍內的substring是回文子串(dp[i][j]) 且(&&) 長度大於當前要記錄的最終長度(j - i + 1 > finalLen)
+ //我們就更新 當前最長的連續回文子串長度、最終起點、最終終點
+ if (dp[i][j] && j - i + 1 > finalLen) {
+ finalLen = j - i + 1;
+ finalStart = i;
+ finalEnd = j;
+ }
+ }
+ }
+ //String.substring這個method的用法是[起點, 終點),包含起點,不包含終點(左閉右開區間),故終點 + 1。
+ return s.substring(finalStart, finalEnd + 1);
+ }
+}
+```
Python:
diff --git a/problems/0654.最大二叉树.md b/problems/0654.最大二叉树.md
index 33a9176e..77d7980f 100644
--- a/problems/0654.最大二叉树.md
+++ b/problems/0654.最大二叉树.md
@@ -25,9 +25,9 @@
给定的数组的大小在 [1, 1000] 之间。
-## 视频讲解
+## 算法公开课
-**《代码随想录》算法视频公开课:[又是构造二叉树,又有很多坑!| LeetCode:654.最大二叉树](https://www.bilibili.com/video/BV1MG411G7ox),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[又是构造二叉树,又有很多坑!| LeetCode:654.最大二叉树](https://www.bilibili.com/video/BV1MG411G7ox),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -310,7 +310,7 @@ class Solution:
def constructMaximumBinaryTree(self, nums: List[int]) -> TreeNode:
return self.traversal(nums, 0, len(nums))
- ```
+```
(版本三) 使用切片
@@ -587,3 +587,4 @@ impl Solution {
+
diff --git a/problems/0669.修剪二叉搜索树.md b/problems/0669.修剪二叉搜索树.md
index 85922a1d..2cfbfefc 100644
--- a/problems/0669.修剪二叉搜索树.md
+++ b/problems/0669.修剪二叉搜索树.md
@@ -20,17 +20,17 @@

-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[你修剪的方式不对,我来给你纠正一下!| LeetCode:669. 修剪二叉搜索树](https://www.bilibili.com/video/BV17P41177ud?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[你修剪的方式不对,我来给你纠正一下!| LeetCode:669. 修剪二叉搜索树](https://www.bilibili.com/video/BV17P41177ud?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
-# 思路
+## 思路
相信看到这道题目大家都感觉是一道简单题(事实上leetcode上也标明是简单)。
但还真的不简单!
-## 递归法
+### 递归法
直接想法就是:递归处理,然后遇到 `root->val < low || root->val > high` 的时候直接return NULL,一波修改,赶紧利落。
@@ -188,7 +188,7 @@ public:
只看代码,其实不太好理解节点是如何移除的,这一块大家可以自己再模拟模拟!
-## 迭代法
+### 迭代法
因为二叉搜索树的有序性,不需要使用栈模拟递归的过程。
@@ -233,7 +233,7 @@ public:
};
```
-# 总结
+## 总结
修剪二叉搜索树其实并不难,但在递归法中大家可看出我费了很大的功夫来讲解如何删除节点的,这个思路其实是比较绕的。
@@ -243,10 +243,10 @@ public:
本题我依然给出递归法和迭代法,初学者掌握递归就可以了,如果想进一步学习,就把迭代法也写一写。
-# 其他语言版本
+## 其他语言版本
-## Java
+### Java
**递归**
@@ -311,7 +311,7 @@ class Solution {
````
-## Python
+### Python
递归法(版本一)
```python
@@ -381,7 +381,7 @@ class Solution:
```
-## Go
+### Go
```go
// 递归
@@ -436,7 +436,7 @@ func trimBST(root *TreeNode, low int, high int) *TreeNode {
```
-## JavaScript版本
+### JavaScript
迭代:
@@ -492,7 +492,7 @@ var trimBST = function (root,low,high) {
}
```
-## TypeScript
+### TypeScript
> 递归法
@@ -540,7 +540,7 @@ function trimBST(root: TreeNode | null, low: number, high: number): TreeNode | n
};
```
-## Scala
+### Scala
递归法:
@@ -557,7 +557,7 @@ object Solution {
}
```
-## rust
+### Rust
// 递归
@@ -590,3 +590,4 @@ impl Solution {
+
diff --git a/problems/0684.冗余连接.md b/problems/0684.冗余连接.md
index 177338dd..c4d62d9b 100644
--- a/problems/0684.冗余连接.md
+++ b/problems/0684.冗余连接.md
@@ -4,11 +4,8 @@
diff --git a/problems/0700.二叉搜索树中的搜索.md b/problems/0700.二叉搜索树中的搜索.md
index 13064f97..bc21bab8 100644
--- a/problems/0700.二叉搜索树中的搜索.md
+++ b/problems/0700.二叉搜索树中的搜索.md
@@ -18,9 +18,9 @@
在上述示例中,如果要找的值是 5,但因为没有节点值为 5,我们应该返回 NULL。
-# 视频讲解
+## 算法公开课
-**《代码随想录》算法视频公开课:[不愧是搜索树,这次搜索有方向了!| LeetCode:700.二叉搜索树中的搜索](https://www.bilibili.com/video/BV1wG411g7sF),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[不愧是搜索树,这次搜索有方向了!| LeetCode:700.二叉搜索树中的搜索](https://www.bilibili.com/video/BV1wG411g7sF),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -415,7 +415,7 @@ object Solution {
}
```
-### rust
+### Rust
递归:
@@ -469,3 +469,4 @@ impl Solution {
+
diff --git a/problems/0701.二叉搜索树中的插入操作.md b/problems/0701.二叉搜索树中的插入操作.md
index fc4351ba..511d161c 100644
--- a/problems/0701.二叉搜索树中的插入操作.md
+++ b/problems/0701.二叉搜索树中的插入操作.md
@@ -23,11 +23,11 @@
* -10^8 <= val <= 10^8
* 新值和原始二叉搜索树中的任意节点值都不同
-# 算法公开课
+## 算法公开课
-**《代码随想录》算法视频公开课:[原来这么简单? | LeetCode:701.二叉搜索树中的插入操作](https://www.bilibili.com/video/BV1Et4y1c78Y?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[原来这么简单? | LeetCode:701.二叉搜索树中的插入操作](https://www.bilibili.com/video/BV1Et4y1c78Y?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
-# 思路
+## 思路
这道题目其实是一道简单题目,**但是题目中的提示:有多种有效的插入方式,还可以重构二叉搜索树,一下子吓退了不少人**,瞬间感觉题目复杂了很多。
@@ -43,7 +43,7 @@
接下来就是遍历二叉搜索树的过程了。
-## 递归
+### 递归
递归三部曲:
@@ -165,7 +165,7 @@ public:
**网上千篇一律的代码,可能会误导大家认为通过递归函数返回节点 这样的写法是天经地义,其实这里是有优化的!**
-## 迭代
+### 迭代
再来看看迭代法,对二叉搜索树迭代写法不熟悉,可以看这篇:[二叉树:二叉搜索树登场!](https://programmercarl.com/0700.二叉搜索树中的搜索.html)
@@ -198,7 +198,7 @@ public:
};
```
-# 总结
+## 总结
首先在二叉搜索树中的插入操作,大家不用恐惧其重构搜索树,其实根本不用重构。
@@ -207,9 +207,9 @@ public:
最后依然给出了迭代的方法,迭代的方法就需要记录当前遍历节点的父节点了,这个和没有返回值的递归函数实现的代码逻辑是一样的。
-# 其他语言版本
+## 其他语言版本
-## Java
+### Java
```java
class Solution {
@@ -254,7 +254,7 @@ class Solution {
}
```
-----
-## Python
+### Python
递归法(版本一)
```python
@@ -371,7 +371,7 @@ class Solution:
```
-----
-## Go
+### Go
递归法
@@ -417,7 +417,7 @@ func insertIntoBST(root *TreeNode, val int) *TreeNode {
}
```
-----
-## JavaScript
+### JavaScript
有返回值的递归写法
@@ -530,7 +530,7 @@ var insertIntoBST = function (root, val) {
};
```
-## TypeScript
+### TypeScript
> 递归-有返回值
@@ -595,7 +595,7 @@ function insertIntoBST(root: TreeNode | null, val: number): TreeNode | null {
```
-## Scala
+### Scala
递归:
@@ -632,7 +632,7 @@ object Solution {
}
```
-### rust
+### Rust
迭代:
@@ -697,3 +697,4 @@ impl Solution {
+
diff --git a/problems/0704.二分查找.md b/problems/0704.二分查找.md
index 75135749..52abf578 100644
--- a/problems/0704.二分查找.md
+++ b/problems/0704.二分查找.md
@@ -5,7 +5,7 @@
-
diff --git a/problems/0714.买卖股票的最佳时机含手续费(动态规划).md b/problems/0714.买卖股票的最佳时机含手续费(动态规划).md
index 1443f147..042de947 100644
--- a/problems/0714.买卖股票的最佳时机含手续费(动态规划).md
+++ b/problems/0714.买卖股票的最佳时机含手续费(动态规划).md
@@ -270,18 +270,29 @@ impl Solution {
**动态规划**
```Rust
impl Solution {
- fn max(a: i32, b: i32) -> i32 {
- if a > b { a } else { b }
- }
pub fn max_profit(prices: Vec
+
diff --git a/problems/1002.查找常用字符.md b/problems/1002.查找常用字符.md
index 9ec3c6c4..a53148b3 100644
--- a/problems/1002.查找常用字符.md
+++ b/problems/1002.查找常用字符.md
@@ -16,6 +16,7 @@
输入:words = ["bella","label","roller"]
输出:["e","l","l"]
+
示例 2:
输入:words = ["cool","lock","cook"]
diff --git a/problems/1020.飞地的数量.md b/problems/1020.飞地的数量.md
index e92b2412..7538d774 100644
--- a/problems/1020.飞地的数量.md
+++ b/problems/1020.飞地的数量.md
@@ -149,7 +149,63 @@ public:
### Java
-深度优先遍历版本:
+深度优先遍历(没有终止条件 + 空間優化(淹沒島嶼,沒有使用visited數組))
+```java
+//DFS
+class Solution {
+ int count = 0;
+ int[][] dir ={
+ {0, 1},
+ {1, 0},
+ {-1, 0},
+ {0, -1}
+ };
+ private void dfs(int[][] grid, int x, int y){
+ if(grid[x][y] == 0)
+ return;
+
+ grid[x][y] = 0;
+ count++;
+
+ for(int i = 0; i < 4; i++){
+ int nextX = x + dir[i][0];
+ int nextY = y + dir[i][1];
+
+ if(nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length)
+ continue;
+ dfs(grid, nextX, nextY);
+ }
+
+ }
+
+ public int numEnclaves(int[][] grid) {
+ for(int i = 0; i < grid.length; i++){
+ if(grid[i][0] == 1)
+ dfs(grid, i, 0);
+ if(grid[i][grid[0].length - 1] == 1)
+ dfs(grid, i, grid[0].length - 1);
+ }
+ //初始化的時候,j 的上下限有調整過,必免重複操作。
+ for(int j = 1; j < grid[0].length - 1; j++){
+ if(grid[0][j] == 1)
+ dfs(grid, 0, j);
+ if(grid[grid.length - 1][j] == 1)
+ dfs(grid, grid.length - 1, j);
+ }
+ count = 0;
+
+ for(int i = 1; i < grid.length - 1; i++){
+ for(int j = 1; j < grid[0].length - 1; j++){
+ if(grid[i][j] == 1)
+ dfs(grid, i, j);
+ }
+ }
+ return count;
+ }
+}
+```
+
+深度优先遍历(没有终止条件)
```java
class Solution {
@@ -206,7 +262,7 @@ class Solution {
}
```
-广度优先遍历版本:
+广度优先遍历(使用visited數組)
```java
class Solution {
@@ -269,6 +325,72 @@ class Solution {
}
```
+廣度优先遍历(空間優化(淹沒島嶼,沒有使用visited數組))
+```java
+//BFS
+class Solution {
+ int count = 0;
+ int[][] dir ={
+ {0, 1},
+ {1, 0},
+ {-1, 0},
+ {0, -1}
+ };
+ private void bfs(int[][] grid, int x, int y){
+ Queue
+
diff --git a/problems/二叉树理论基础.md b/problems/二叉树理论基础.md
index 4098cf1f..184dba60 100644
--- a/problems/二叉树理论基础.md
+++ b/problems/二叉树理论基础.md
@@ -8,8 +8,11 @@
# 二叉树理论基础篇
+## 算法公开课
-《代码随想录》算法视频公开课:[关于二叉树,你该了解这些!](https://www.bilibili.com/video/BV1Hy4y1t7ij),相信结合视频在看本篇题解,更有助于大家对本题的理解。
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[关于二叉树,你该了解这些!](https://www.bilibili.com/video/BV1Hy4y1t7ij),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+
+## 题目分类
题目分类大纲如下:
@@ -189,8 +192,7 @@ struct TreeNode {
## 其他语言版本
-
-Java:
+### Java:
```java
public class TreeNode {
@@ -208,8 +210,7 @@ public class TreeNode {
}
```
-
-Python:
+### Python:
```python
class TreeNode:
@@ -219,7 +220,7 @@ class TreeNode:
self.right = right
```
-Go:
+### Go:
```go
type TreeNode struct {
@@ -229,7 +230,7 @@ type TreeNode struct {
}
```
-JavaScript:
+### JavaScript:
```javascript
function TreeNode(val, left, right) {
@@ -239,7 +240,7 @@ function TreeNode(val, left, right) {
}
```
-TypeScript:
+### TypeScript:
```typescript
class TreeNode {
@@ -254,7 +255,7 @@ class TreeNode {
}
```
-Swift:
+### Swift:
```Swift
class TreeNode
+
diff --git a/problems/二叉树的迭代遍历.md b/problems/二叉树的迭代遍历.md
index 8b241465..69007995 100644
--- a/problems/二叉树的迭代遍历.md
+++ b/problems/二叉树的迭代遍历.md
@@ -4,16 +4,17 @@
+
diff --git a/problems/剑指Offer58-II.左旋转字符串.md b/problems/剑指Offer58-II.左旋转字符串.md
index 6cd88456..008b7915 100644
--- a/problems/剑指Offer58-II.左旋转字符串.md
+++ b/problems/剑指Offer58-II.左旋转字符串.md
@@ -24,7 +24,7 @@
限制:
1 <= k < s.length <= 10000
-# 思路
+## 思路
为了让本题更有意义,提升一下本题难度:**不能申请额外空间,只能在本串上操作**。
@@ -71,7 +71,7 @@ public:
是不是发现这代码也太简单了,哈哈。
-# 总结
+## 总结
此时我们已经反转好多次字符串了,来一起回顾一下吧。
@@ -86,7 +86,7 @@ public:
好了,反转字符串一共就介绍到这里,相信大家此时对反转字符串的常见操作已经很了解了。
-# 题外话
+## 题外话
一些同学热衷于使用substr,来做这道题。
其实使用substr 和 反转 时间复杂度是一样的 ,都是O(n),但是使用substr申请了额外空间,所以空间复杂度是O(n),而反转方法的空间复杂度是O(1)。
@@ -96,7 +96,8 @@ public:
## 其他语言版本
-Java:
+### Java:
+
```java
class Solution {
public String reverseLeftWords(String s, int n) {
@@ -141,7 +142,7 @@ class Solution {
}
```
-python:
+### python:
(版本一)使用切片
```python
@@ -211,7 +212,7 @@ class Solution:
```
-Go:
+### Go:
```go
func reverseLeftWords(s string, n int) string {
@@ -234,8 +235,7 @@ func reverse(b []byte, left, right int){
}
```
-
-JavaScript:
+### JavaScript:
```javascript
var reverseLeftWords = function(s, n) {
@@ -279,7 +279,7 @@ var reverseLeftWords = function (s, n) {
};
```
-TypeScript:
+### TypeScript:
```typescript
function reverseLeftWords(s: string, n: number): string {
@@ -311,7 +311,7 @@ function reverseLeftWords(s: string, n: number): string {
};
```
-Swift:
+### Swift:
```swift
func reverseLeftWords(_ s: String, _ n: Int) -> String {
@@ -358,8 +358,7 @@ function reverse(&$s, $start, $end) {
}
```
-
-Scala:
+### Scala:
```scala
object Solution {
@@ -388,7 +387,7 @@ object Solution {
}
```
-Rust:
+### Rust:
```Rust
impl Solution {
@@ -419,3 +418,4 @@ impl Solution {
+
diff --git a/problems/双指针总结.md b/problems/双指针总结.md
index 04a8cb9a..6621e039 100644
--- a/problems/双指针总结.md
+++ b/problems/双指针总结.md
@@ -8,7 +8,8 @@
相信大家已经对双指针法很熟悉了,但是双指针法并不隶属于某一种数据结构,我们在讲解数组,链表,字符串都用到了双指针法,所有有必要针对双指针法做一个总结。
-# 数组篇
+# 双指针总结篇
+## 数组篇
在[数组:就移除个元素很难么?](https://programmercarl.com/0027.移除元素.html)中,原地移除数组上的元素,我们说到了数组上的元素,不能真正的删除,只能覆盖。
@@ -26,7 +27,7 @@ for (int i = 0; i < array.size(); i++) {
所以此时使用双指针法才展现出效率的优势:**通过两个指针在一个for循环下完成两个for循环的工作。**
-# 字符串篇
+## 字符串篇
在[字符串:这道题目,使用库函数一行代码搞定](https://programmercarl.com/0344.反转字符串.html)中讲解了反转字符串,注意这里强调要原地反转,要不然就失去了题目的意义。
@@ -48,7 +49,7 @@ for (int i = 0; i < array.size(); i++) {
**主要还是大家用erase用的比较随意,一定要注意for循环下用erase的情况,一般可以用双指针写效率更高!**
-# 链表篇
+## 链表篇
翻转链表是现场面试,白纸写代码的好题,考察了候选者对链表以及指针的熟悉程度,而且代码也不长,适合在白纸上写。
@@ -62,7 +63,7 @@ for (int i = 0; i < array.size(); i++) {
那么找到环的入口,其实需要点简单的数学推理,我在文章中把找环的入口清清楚楚的推理的一遍,如果对找环入口不够清楚的同学建议自己看一看[链表:环找到了,那入口呢?](https://programmercarl.com/0142.环形链表II.html)。
-# N数之和篇
+## N数之和篇
在[哈希表:解决了两数之和,那么能解决三数之和么?](https://programmercarl.com/0015.三数之和.html)中,讲到使用哈希法可以解决1.两数之和的问题
@@ -87,7 +88,7 @@ for (int i = 0; i < array.size(); i++) {
同样的道理,五数之和,n数之和都是在这个基础上累加。
-# 总结
+## 总结
本文中一共介绍了leetcode上九道使用双指针解决问题的经典题目,除了链表一些题目一定要使用双指针,其他题目都是使用双指针来提高效率,一般是将O(n^2)的时间复杂度,降为$O(n)$。
diff --git a/problems/哈希表总结.md b/problems/哈希表总结.md
index 9ee84f99..67506363 100644
--- a/problems/哈希表总结.md
+++ b/problems/哈希表总结.md
@@ -7,8 +7,10 @@
> 哈希表总结篇如约而至
+# 哈希表总结篇
-# 哈希表理论基础
+
+## 哈希表理论基础
在[关于哈希表,你该了解这些!](https://programmercarl.com/哈希表理论基础.html)中,我们介绍了哈希表的基础理论知识,不同于枯燥的讲解,这里介绍了都是对刷题有帮助的理论知识点。
@@ -32,9 +34,9 @@
**只有对这些数据结构的底层实现很熟悉,才能灵活使用,否则很容易写出效率低下的程序**。
-# 哈希表经典题目
+## 哈希表经典题目
-## 数组作为哈希表
+### 数组作为哈希表
一些应用场景就是为数组量身定做的。
@@ -51,7 +53,7 @@
**上面两道题目用map确实可以,但使用map的空间消耗要比数组大一些,因为map要维护红黑树或者符号表,而且还要做哈希函数的运算。所以数组更加简单直接有效!**
-## set作为哈希表
+### set作为哈希表
在[349. 两个数组的交集](https://programmercarl.com/0349.两个数组的交集.html)中我们给出了什么时候用数组就不行了,需要用set。
@@ -75,7 +77,7 @@ std::set和std::multiset底层实现都是红黑树,std::unordered_set的底
在[202.快乐数](https://programmercarl.com/0202.快乐数.html)中,我们再次使用了unordered_set来判断一个数是否重复出现过。
-## map作为哈希表
+### map作为哈希表
在[1.两数之和](https://programmercarl.com/0001.两数之和.html)中map正式登场。
@@ -110,7 +112,7 @@ std::unordered_map 底层实现为哈希,std::map 和std::multimap 的底层
所以18. 四数之和,15.三数之和都推荐使用双指针法!
-# 总结
+## 总结
对于哈希表的知识相信很多同学都知道,但是没有成体系。
@@ -123,9 +125,8 @@ std::unordered_map 底层实现为哈希,std::map 和std::multimap 的底层
-
-
+
diff --git a/problems/哈希表理论基础.md b/problems/哈希表理论基础.md
index 0ab17ec0..3055875a 100644
--- a/problems/哈希表理论基础.md
+++ b/problems/哈希表理论基础.md
@@ -8,6 +8,8 @@
+# 哈希表理论基础
+
## 哈希表
首先什么是 哈希表,哈希表(英文名字为Hash table,国内也有一些算法书籍翻译为散列表,大家看到这两个名称知道都是指hash table就可以了)。
diff --git a/problems/回溯总结.md b/problems/回溯总结.md
index 21d78bc2..f2e46829 100644
--- a/problems/回溯总结.md
+++ b/problems/回溯总结.md
@@ -8,7 +8,9 @@
> 20张树形结构图、14道精选回溯题目,21篇回溯法精讲文章,由浅入深,一气呵成,这是全网最强回溯算法总结!
-# 回溯法理论基础
+# 回溯总结篇
+
+## 回溯法理论基础
转眼间[「代码随想录」](https://img-blog.csdnimg.cn/20200815195519696.png)里已经分享连续讲解了21天的回溯算法,是时候做一个大总结了,本篇高能,需要花费很大的精力来看!
@@ -51,10 +53,10 @@ void backtracking(参数) {
**事实证明这个模板会伴随整个回溯法系列!**
-# 组合问题
-
## 组合问题
+### 组合问题
+
在[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)中,我们开始用回溯法解决第一道题目:组合问题。
我在文中开始的时候给大家列举k层for循环例子,进而得出都是同样是暴力解法,为什么要用回溯法!
@@ -82,9 +84,9 @@ void backtracking(参数) {
**在for循环上做剪枝操作是回溯法剪枝的常见套路!** 后面的题目还会经常用到。
-## 组合总和
+### 组合总和
-### 组合总和(一)
+#### 组合总和(一)
在[回溯算法:求组合总和!](https://programmercarl.com/0216.组合总和III.html)中,相当于 [回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)加了一个元素总和的限制。
@@ -99,7 +101,7 @@ void backtracking(参数) {
所以剪枝的代码可以在for循环加上 `i <= 9 - (k - path.size()) + 1` 的限制!
-### 组合总和(二)
+#### 组合总和(二)
在[回溯算法:求组合总和(二)](https://programmercarl.com/0039.组合总和.html)中讲解的组合总和问题,和[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html),[回溯算法:求组合总和!](https://programmercarl.com/0216.组合总和III.html)和区别是:本题没有数量要求,可以无限重复,但是有总和的限制,所以间接的也是有个数的限制。
@@ -128,7 +130,7 @@ for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target;

-### 组合总和(三)
+#### 组合总和(三)
在[回溯算法:求组合总和(三)](https://programmercarl.com/0040.组合总和II.html)中集合元素会有重复,但要求解集不能包含重复的组合。
@@ -151,7 +153,7 @@ for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target;
对于去重,其实排列和子集问题也是一样的道理。
-## 多个集合求组合
+### 多个集合求组合
在[回溯算法:电话号码的字母组合](https://programmercarl.com/0017.电话号码的字母组合.html)中,开始用多个集合来求组合,还是熟悉的模板题目,但是有一些细节。
@@ -167,7 +169,7 @@ for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target;
其实本题不算难,但也处处是细节,还是要反复琢磨。
-# 切割问题
+## 切割问题
在[回溯算法:分割回文串](https://programmercarl.com/0131.分割回文串.html)中,我们开始讲解切割问题,虽然最后代码看起来好像是一道模板题,但是从分析到学会套用这个模板,是比较难的。
@@ -192,9 +194,9 @@ for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target;

-# 子集问题
+## 子集问题
-## 子集问题(一)
+### 子集问题(一)
在[回溯算法:求子集问题!](https://programmercarl.com/0078.子集.html)中讲解了子集问题,**在树形结构中子集问题是要收集所有节点的结果,而组合问题是收集叶子节点的结果**。
@@ -219,7 +221,7 @@ if (startIndex >= nums.size()) { // 终止条件可以不加
}
```
-## 子集问题(二)
+### 子集问题(二)
在[回溯算法:求子集问题(二)](https://programmercarl.com/0090.子集II.html)中,开始针对子集问题进行去重。
@@ -229,7 +231,7 @@ if (startIndex >= nums.size()) { // 终止条件可以不加

-## 递增子序列
+### 递增子序列
在[回溯算法:递增子序列](https://programmercarl.com/0491.递增子序列.html)中,处处都能看到子集的身影,但处处是陷阱,值得好好琢磨琢磨!
@@ -247,9 +249,9 @@ if (startIndex >= nums.size()) { // 终止条件可以不加
**相信这个图胜过千言万语的解释了**。
-# 排列问题
+## 排列问题
-## 排列问题(一)
+### 排列问题(一)
[回溯算法:排列问题!](https://programmercarl.com/0046.全排列.html) 又不一样了。
@@ -266,7 +268,7 @@ if (startIndex >= nums.size()) { // 终止条件可以不加
* 每层都是从0开始搜索而不是startIndex
* 需要used数组记录path里都放了哪些元素了
-## 排列问题(二)
+### 排列问题(二)
排列问题也要去重了,在[回溯算法:排列问题(二)](https://programmercarl.com/0047.全排列II.html)中又一次强调了“树层去重”和“树枝去重”。
@@ -290,7 +292,7 @@ if (startIndex >= nums.size()) { // 终止条件可以不加
本题used数组即是记录path里都放了哪些元素,同时也用来去重,一举两得。
-# 去重问题
+## 去重问题
以上我都是统一使用used数组来去重的,其实使用set也可以用来去重!
@@ -310,7 +312,7 @@ if (startIndex >= nums.size()) { // 终止条件可以不加
used数组可是全局变量,每层与每层之间公用一个used数组,所以空间复杂度是O(n + n),最终空间复杂度还是O(n)。
-# 重新安排行程(图论额外拓展)
+## 重新安排行程(图论额外拓展)
之前说过,有递归的地方就有回溯,深度优先搜索也是用递归来实现的,所以往往伴随着回溯。
@@ -327,9 +329,9 @@ used数组可是全局变量,每层与每层之间公用一个used数组,所
本题其实是一道深度优先搜索的题目,但是我完全使用回溯法的思路来讲解这道题题目,**算是给大家拓展一下思维方式,其实深搜和回溯也是分不开的,毕竟最终都是用递归**。
-# 棋盘问题
+## 棋盘问题
-## N皇后问题
+### N皇后问题
在[回溯算法:N皇后问题](https://programmercarl.com/0051.N皇后.html)中终于迎来了传说中的N皇后。
@@ -349,7 +351,7 @@ used数组可是全局变量,每层与每层之间公用一个used数组,所
-## 解数独问题
+### 解数独问题
在[回溯算法:解数独](https://programmercarl.com/0037.解数独.html)中要征服回溯法的最后一道山峰。
@@ -373,7 +375,7 @@ used数组可是全局变量,每层与每层之间公用一个used数组,所
**这样,解数独这么难的问题也被我们攻克了**。
-# 性能分析
+## 性能分析
**关于回溯算法的复杂度分析在网上的资料鱼龙混杂,一些所谓的经典面试书籍不讲回溯算法,算法书籍对这块也避而不谈,感觉就像是算法里模糊的边界**。
@@ -410,7 +412,7 @@ N皇后问题分析:
**一般说道回溯算法的复杂度,都说是指数级别的时间复杂度,这也算是一个概括吧!**
-# 总结
+## 总结
**[「代码随想录」](https://img-blog.csdnimg.cn/20200815195519696.png)历时21天,14道经典题目分析,20张树形图,21篇回溯法精讲文章,从组合到切割,从子集到排列,从棋盘问题到最后的复杂度分析**,至此收尾了。
@@ -449,3 +451,4 @@ N皇后问题分析:
+
diff --git a/problems/回溯算法去重问题的另一种写法.md b/problems/回溯算法去重问题的另一种写法.md
index 4e09b925..2be79805 100644
--- a/problems/回溯算法去重问题的另一种写法.md
+++ b/problems/回溯算法去重问题的另一种写法.md
@@ -246,8 +246,7 @@ used数组可是全局变量,每层与每层之间公用一个used数组,所
## 其他语言版本
-
-Java:
+### Java
**47.全排列II**
@@ -350,7 +349,7 @@ class Solution {
}
}
```
-Python:
+### Python
**90.子集II**
@@ -432,7 +431,7 @@ class Solution:
```
-JavaScript:
+### JavaScript
**90.子集II**
@@ -510,7 +509,7 @@ function permuteUnique(nums) {
};
```
-TypeScript:
+### TypeScript
**90.子集II**
@@ -592,7 +591,7 @@ function permuteUnique(nums: number[]): number[][] {
};
```
-Rust:
+### Rust
**90.子集II**:
@@ -713,3 +712,4 @@ impl Solution {
+
diff --git a/problems/回溯算法理论基础.md b/problems/回溯算法理论基础.md
index f11dbaef..dff1823c 100644
--- a/problems/回溯算法理论基础.md
+++ b/problems/回溯算法理论基础.md
@@ -6,13 +6,19 @@
# 回溯算法理论基础
-## 题目分类大纲如下:
+## 题目分类
-可以配合我的B站视频:[带你学透回溯算法(理论篇)](https://www.bilibili.com/video/BV1cy4y167mM/) 一起学习!
+## 算法公开课
-## 什么是回溯法
+
+
+**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[带你学透回溯算法(理论篇)](https://www.bilibili.com/video/BV1cy4y167mM/),相信结合视频再看本篇题解,更有助于大家对本题的理解。**
+
+## 理论基础
+
+### 什么是回溯法
回溯法也可以叫做回溯搜索法,它是一种搜索的方式。
@@ -22,7 +28,7 @@
**所以以下讲解中,回溯函数也就是递归函数,指的都是一个函数**。
-## 回溯法的效率
+### 回溯法的效率
回溯法的性能如何呢,这里要和大家说清楚了,**虽然回溯法很难,很不好理解,但是回溯法并不是什么高效的算法**。
@@ -34,7 +40,7 @@
此时大家应该好奇了,都什么问题,这么牛逼,只能暴力搜索。
-## 回溯法解决的问题
+### 回溯法解决的问题
回溯法,一般可以解决如下几种问题:
@@ -55,7 +61,7 @@
记住组合无序,排列有序,就可以了。
-## 如何理解回溯法
+### 如何理解回溯法
**回溯法解决的问题都可以抽象为树形结构**,是的,我指的是所有回溯法的问题都可以抽象为树形结构!
@@ -66,7 +72,7 @@
这块可能初学者还不太理解,后面的回溯算法解决的所有题目中,我都会强调这一点并画图举相应的例子,现在有一个印象就行。
-## 回溯法模板
+### 回溯法模板
这里给出Carl总结的回溯算法模板。
@@ -173,3 +179,4 @@ void backtracking(参数) {
+
diff --git a/problems/图论并查集理论基础.md b/problems/图论并查集理论基础.md
new file mode 100644
index 00000000..5cd753e9
--- /dev/null
+++ b/problems/图论并查集理论基础.md
@@ -0,0 +1,433 @@
+
+# 并查集理论基础
+
+图论中,关于深搜和广搜我们在这里:[钥匙和房间](https://mp.weixin.qq.com/s/E9NlJy9PW1oJuD8N2EURoQ) 已经更新完毕了。
+
+接下来我们来讲一下并查集,首先当然是并查集理论基础。
+
+## 背景
+
+首先要知道并查集可以解决什么问题呢?
+
+并查集常用来解决连通性问题。
+
+大白话就是当我们需要判断两个元素是否在同一个集合里的时候,我们就要想到用并查集。
+
+并查集主要有两个功能:
+
+* 将两个元素添加到一个集合中。
+* 判断两个元素在不在同一个集合
+
+接下来围绕并查集的这两个功能来展开讲解。
+
+## 原理讲解
+
+从代码层面,我们如何将两个元素添加到同一个集合中呢。
+
+此时有录友会想到:可以把他放到同一个数组里或者set 或者 map 中,这样就表述两个元素在同一个集合。
+
+那么问题来了,对这些元素分门别类,可不止一个集合,可能是很多集合,成百上千,那么要定义这么多个数组吗?
+
+有录友想,那可以定义一个二维数组。
+
+但如果我们要判断两个元素是否在同一个集合里的时候 我们又能怎么办? 只能把而二维数组都遍历一遍。
+
+而且每当想添加一个元素到某集合的时候,依然需要把把二维数组组都遍历一遍,才知道要放在哪个集合里。
+
+这仅仅是一个粗略的思路,如果沿着这个思路去实现代码,非常复杂,因为管理集合还需要很多逻辑。
+
+那么我们来换一个思路来看看。
+
+我们将三个元素A,B,C (分别是数字)放在同一个集合,其实就是将三个元素连通在一起,如何连通呢。
+
+只需要用一个一维数组来表示,即:father[A] = B,father[B] = C 这样就表述 A 与 B 与 C连通了(有向连通图)。
+
+代码如下:
+
+``` CPP
+// 将v,u 这条边加入并查集
+void join(int u, int v) {
+ u = find(u); // 寻找u的根
+ v = find(v); // 寻找v的根
+ if (u == v) return; // 如果发现根相同,则说明在一个集合,不用两个节点相连直接返回
+ father[v] = u;
+}
+```
+
+可能有录友想,这样我可以知道 A 连通 B,因为 A 是索引下标,根据 father[A]的数值就知道 A 连通 B。那怎么知道 B 连通 A呢?
+
+我们的目的是判断这三个元素是否在同一个集合里,知道 A 连通 B 就已经足够了。
+
+这里要讲到寻根思路,只要 A ,B,C 在同一个根下就是同一个集合。
+
+给出A元素,就可以通过 father[A] = B,father[B] = C,找到根为 C。
+
+给出B元素,就可以通过 father[B] = C,找到根也为为 C,说明 A 和 B 是在同一个集合里。
+大家会想第一段代码里find函数是如何实现的呢?其实就是通过数组下标找到数组元素,一层一层寻根过程,代码如下:
+
+```CPP
+// 并查集里寻根的过程
+int find(int u) {
+ if (u == father[u]) return u; // 如果根就是自己,直接返回
+ else return find(father[u]); // 如果根不是自己,就根据数组下标一层一层向下找
+}
+
+```
+
+
+如何表示 C 也在同一个元素里呢? 我们需要 father[C] = C,即C的根也为C,这样就方便表示 A,B,C 都在同一个集合里了。
+
+所以father数组初始化的时候要 father[i] = i,默认自己指向自己。
+
+代码如下:
+
+```CPP
+// 并查集初始化
+void init() {
+ for (int i = 0; i < n; ++i) {
+ father[i] = i;
+ }
+}
+```
+
+最后我们如何判断两个元素是否在同一个集合里,如果通过 find函数 找到 两个元素属于同一个根的话,那么这两个元素就是同一个集合,代码如下:
+
+
+```CPP
+// 判断 u 和 v是否找到同一个根
+bool isSame(int u, int v) {
+ u = find(u);
+ v = find(v);
+ return u == v;
+}
+```
+
+## 路径压缩
+
+在实现 find 函数的过程中,我们知道,通过递归的方式,不断获取father数组下标对应的数值,最终找到这个集合的根。
+
+搜索过程像是一个多叉树中从叶子到根节点的过程,如图:
+
+
+
+如果这棵多叉树高度很深的话,每次find函数 去寻找跟的过程就要递归很多次。
+
+我们的目的只需要知道这些节点在同一个根下就可以,所以对这棵多叉树的构造只需要这样就可以了,如图:
+
+
+
+除了根节点其他所有节点都挂载根节点下,这样我们在寻根的时候就很快,只需要一步,
+
+如果我们想达到这样的效果,就需要 **路径压缩**,将非根节点的所有节点直接指向根节点。
+那么在代码层面如何实现呢?
+
+我们只需要在递归的过程中,让 father[u] 接住 递归函数 find(father[u]) 的返回结果。
+
+因为 find 函数向上寻找根节点,father[u] 表述 u 的父节点,那么让 father[u] 直接获取 find函数 返回的根节点,这样就让节点 u 的父节点 变成根节点。
+
+代码如下,注意看注释,路径压缩就一行代码:
+
+```CPP
+// 并查集里寻根的过程
+int find(int u) {
+ if (u == father[u]) return u;
+ else return father[u] = find(father[u]); // 路径压缩
+}
+```
+
+以上代码在C++中,可以用三元表达式来精简一下,代码如下:
+
+```CPP
+int find(int u) {
+ return u == father[u] ? u : father[u] = find(father[u]);
+}
+
+```
+
+相信不少录友在学习并查集的时候,对上面这三行代码实现的 find函数 很熟悉,但理解上却不够深入,仅仅知道这行代码很好用,不知道这里藏着路径压缩的过程。
+
+所以对于算法初学者来说,直接看精简代码学习是不太友好的,往往忽略了很多细节。
+
+## 代码模板
+
+那么此时并查集的模板就出来了, 整体模板C++代码如下:
+
+```CPP
+int n = 1005; // n根据题目中节点数量而定,一般比节点数量大一点就好
+vector
+
diff --git a/problems/数组总结篇.md b/problems/数组总结篇.md
index ef962187..7550ce02 100644
--- a/problems/数组总结篇.md
+++ b/problems/数组总结篇.md
@@ -4,9 +4,9 @@
+
diff --git a/problems/栈与队列理论基础.md b/problems/栈与队列理论基础.md
index 0075deb6..ad748e48 100644
--- a/problems/栈与队列理论基础.md
+++ b/problems/栈与队列理论基础.md
@@ -4,8 +4,11 @@
+
diff --git a/problems/背包理论基础01背包-1.md b/problems/背包理论基础01背包-1.md
index 9df2fc4c..bd3191dc 100644
--- a/problems/背包理论基础01背包-1.md
+++ b/problems/背包理论基础01背包-1.md
@@ -338,6 +338,64 @@ public class BagProblem {
```
+```java
+import java.util.Arrays;
+
+public class BagProblem {
+ public static void main(String[] args) {
+ int[] weight = {1,3,4};
+ int[] value = {15,20,30};
+ int bagSize = 4;
+ testWeightBagProblem(weight,value,bagSize);
+ }
+
+ /**
+ * 初始化 dp 数组做了简化(给物品增加冗余维)。这样初始化dp数组,默认全为0即可。
+ * dp[i][j] 表示从下标为[0 - i-1]的物品里任意取,放进容量为j的背包,价值总和最大是多少。
+ * 其实是模仿背包重量从 0 开始,背包容量 j 为 0 的话,即dp[i][0],无论是选取哪些物品,背包价值总和一定为 0。
+ * 可选物品也可以从无开始,也就是没有物品可选,即dp[0][j],这样无论背包容量为多少,背包价值总和一定为 0。
+ * @param weight 物品的重量
+ * @param value 物品的价值
+ * @param bagSize 背包的容量
+ */
+ public static void testWeightBagProblem(int[] weight, int[] value, int bagSize){
+
+ // 创建dp数组
+ int goods = weight.length; // 获取物品的数量
+ int[][] dp = new int[goods + 1][bagSize + 1]; // 给物品增加冗余维,i = 0 表示没有物品可选
+
+ // 初始化dp数组,默认全为0即可
+ // 填充dp数组
+ for (int i = 1; i <= goods; i++) {
+ for (int j = 1; j <= bagSize; j++) {
+ if (j < weight[i - 1]) { // i - 1 对应物品 i
+ /**
+ * 当前背包的容量都没有当前物品i大的时候,是不放物品i的
+ * 那么前i-1个物品能放下的最大价值就是当前情况的最大价值
+ */
+ dp[i][j] = dp[i - 1][j];
+ } else {
+ /**
+ * 当前背包的容量可以放下物品i
+ * 那么此时分两种情况:
+ * 1、不放物品i
+ * 2、放物品i
+ * 比较这两种情况下,哪种背包中物品的最大价值最大
+ */
+ dp[i][j] = Math.max(dp[i - 1][j] , dp[i - 1][j - weight[i - 1]] + value[i - 1]); // i - 1 对应物品 i
+ }
+ }
+ }
+
+ // 打印dp数组
+ for(int[] arr : dp){
+ System.out.println(Arrays.toString(arr));
+ }
+ }
+}
+
+```
+
### python
无参数版
```python
diff --git a/problems/链表总结篇.md b/problems/链表总结篇.md
index cfbafc45..dacd4dee 100644
--- a/problems/链表总结篇.md
+++ b/problems/链表总结篇.md
@@ -3,7 +3,7 @@
+
diff --git a/problems/链表理论基础.md b/problems/链表理论基础.md
index a09974df..da5a1b02 100644
--- a/problems/链表理论基础.md
+++ b/problems/链表理论基础.md
@@ -16,15 +16,15 @@
如图所示:

-# 链表的类型
+## 链表的类型
接下来说一下链表的几种类型:
-## 单链表
+### 单链表
刚刚说的就是单链表。
-## 双链表
+### 双链表
单链表中的指针域只能指向节点的下一个节点。
@@ -35,7 +35,7 @@
如图所示:

-## 循环链表
+### 循环链表
循环链表,顾名思义,就是链表首尾相连。
@@ -44,7 +44,7 @@

-# 链表的存储方式
+## 链表的存储方式
了解完链表的类型,再来说一说链表在内存中的存储方式。
@@ -60,7 +60,7 @@
这个链表起始节点为2, 终止节点为7, 各个节点分布在内存的不同地址空间上,通过指针串联在一起。
-# 链表的定义
+## 链表的定义
接下来说一说链表的定义。
@@ -100,9 +100,9 @@ head->val = 5;
所以如果不定义构造函数使用默认构造函数的话,在初始化的时候就不能直接给变量赋值!
-# 链表的操作
+## 链表的操作
-## 删除节点
+### 删除节点
删除D节点,如图所示:
@@ -116,7 +116,7 @@ head->val = 5;
其他语言例如Java、Python,就有自己的内存回收机制,就不用自己手动释放了。
-## 添加节点
+### 添加节点
如图所示:
@@ -126,7 +126,7 @@ head->val = 5;
但是要注意,要是删除第五个节点,需要从头节点查找到第四个节点通过next指针进行删除操作,查找的时间复杂度是O(n)。
-# 性能分析
+## 性能分析
再把链表的特性和数组的特性进行一个对比,如图所示:
@@ -143,8 +143,7 @@ head->val = 5;
## 其他语言版本
-
-Java:
+### Java:
```java
public class ListNode {
@@ -171,7 +170,7 @@ public class ListNode {
}
```
-JavaScript:
+### JavaScript:
```javascript
class ListNode {
@@ -184,7 +183,7 @@ class ListNode {
}
```
-TypeScript:
+### TypeScript:
```typescript
class ListNode {
@@ -197,7 +196,7 @@ class ListNode {
}
```
-Python:
+### Python:
```python
class ListNode:
@@ -206,7 +205,7 @@ class ListNode:
self.next = next
```
-Go:
+### Go:
```go
type ListNode struct {
@@ -215,7 +214,7 @@ type ListNode struct {
}
```
-Scala:
+### Scala:
```scala
class ListNode(_x: Int = 0, _next: ListNode = null) {
@@ -224,7 +223,7 @@ class ListNode(_x: Int = 0, _next: ListNode = null) {
}
```
-Rust:
+### Rust:
```rust
#[derive(PartialEq, Eq, Clone, Debug)]
@@ -246,3 +245,4 @@ impl
+
diff --git a/problems/面试题02.07.链表相交.md b/problems/面试题02.07.链表相交.md
index 75e03116..833eadca 100644
--- a/problems/面试题02.07.链表相交.md
+++ b/problems/面试题02.07.链表相交.md
@@ -34,6 +34,7 @@

+
## 思路
@@ -101,7 +102,7 @@ public:
## 其他语言版本
-Java:
+### Java:
```Java
public class Solution {
@@ -150,8 +151,7 @@ public class Solution {
}
```
-
-Python:
+### Python:
```python
@@ -280,7 +280,7 @@ class Solution:
return pointerA
```
-Go:
+### Go:
```go
func getIntersectionNode(headA, headB *ListNode) *ListNode {
@@ -341,7 +341,7 @@ func getIntersectionNode(headA, headB *ListNode) *ListNode {
}
```
-JavaScript:
+### JavaScript:
```js
var getListLen = function(head) {
@@ -376,7 +376,7 @@ var getIntersectionNode = function(headA, headB) {
};
```
-TypeScript:
+### TypeScript:
```typescript
function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {
@@ -413,7 +413,7 @@ function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): Li
};
```
-C:
+### C:
```c
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
@@ -452,7 +452,7 @@ ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
}
```
-Scala:
+### Scala:
```scala
object Solution {
@@ -508,3 +508,4 @@ object Solution {
+