diff --git a/problems/0024.两两交换链表中的节点.md b/problems/0024.两两交换链表中的节点.md
index 905a0539..10337a7f 100644
--- a/problems/0024.两两交换链表中的节点.md
+++ b/problems/0024.两两交换链表中的节点.md
@@ -337,5 +337,48 @@ object Solution {
}
```
+PHP:
+```php
+//虚拟头结点
+function swapPairs($head) {
+ if ($head == null || $head->next == null) {
+ return $head;
+ }
+
+ $dummyNode = new ListNode(0, $head);
+ $preNode = $dummyNode; //虚拟头结点
+ $curNode = $head;
+ $nextNode = $head->next;
+ while($curNode && $nextNode) {
+ $nextNextNode = $nextNode->next; //存下一个节点
+ $nextNode->next = $curNode; //交换curHead 和 nextHead
+ $curNode->next = $nextNextNode;
+ $preNode->next = $nextNode; //上一个节点的下一个指向指向nextHead
+
+ //更新当前的几个指针
+ $preNode = $preNode->next->next;
+ $curNode = $nextNextNode;
+ $nextNode = $nextNextNode->next;
+ }
+
+ return $dummyNode->next;
+}
+
+//递归版本
+function swapPairs($head)
+{
+ // 终止条件
+ if ($head === null || $head->next === null) {
+ return $head;
+ }
+
+ //结果要返回的头结点
+ $next = $head->next;
+ $head->next = $this->swapPairs($next->next); //当前头结点->next指向更新
+ $next->next = $head; //当前第二个节点的->next指向更新
+ return $next; //返回翻转后的头结点
+}
+```
+
-----------------------
diff --git a/problems/0027.移除元素.md b/problems/0027.移除元素.md
index 12f88c75..33e0c8c1 100644
--- a/problems/0027.移除元素.md
+++ b/problems/0027.移除元素.md
@@ -146,7 +146,7 @@ public:
};
```
-
+
## 相关题目推荐
* 26.删除排序数组中的重复项
@@ -154,10 +154,6 @@ public:
* 844.比较含退格的字符串
* 977.有序数组的平方
-
-
-
-
## 其他语言版本
@@ -165,18 +161,35 @@ Java:
```java
class Solution {
public int removeElement(int[] nums, int val) {
-
// 快慢指针
- int fastIndex = 0;
- int slowIndex;
- for (slowIndex = 0; fastIndex < nums.length; fastIndex++) {
+ int slowIndex = 0;
+ for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) {
if (nums[fastIndex] != val) {
nums[slowIndex] = nums[fastIndex];
slowIndex++;
}
}
return slowIndex;
-
+ }
+}
+```
+```java
+//相向双指针法
+class Solution {
+ public int removeElement(int[] nums, int val) {
+ int left = 0;
+ int right = nums.length - 1;
+ while(right >= 0 && nums[right] == val) right--; //将right移到从右数第一个值不为val的位置
+ while(left <= right) {
+ if(nums[left] == val) { //left位置的元素需要移除
+ //将right位置的元素移到left(覆盖),right位置移除
+ nums[left] = nums[right];
+ right--;
+ }
+ left++;
+ while(right >= 0 && nums[right] == val) right--;
+ }
+ return left;
}
}
```
diff --git a/problems/0035.搜索插入位置.md b/problems/0035.搜索插入位置.md
index f2bbb8ca..5ed3ac56 100644
--- a/problems/0035.搜索插入位置.md
+++ b/problems/0035.搜索插入位置.md
@@ -226,7 +226,32 @@ class Solution {
}
}
```
+```java
+//第二种二分法:左闭右开
+public int searchInsert(int[] nums, int target) {
+ int left = 0;
+ int right = nums.length;
+ while (left < right) { //左闭右开 [left, right)
+ int middle = left + ((right - left) >> 1);
+ if (nums[middle] > target) {
+ right = middle; // target 在左区间,在[left, middle)中
+ } else if (nums[middle] < target) {
+ left = middle + 1; // target 在右区间,在 [middle+1, right)中
+ } else { // nums[middle] == target
+ return middle; // 数组中找到目标值的情况,直接返回下标
+ }
+ }
+ // 目标值在数组所有元素之前 [0,0)
+ // 目标值插入数组中的位置 [left, right) ,return right 即可
+ // 目标值在数组所有元素之后的情况 [left, right),因为是右开区间,所以 return right
+ return right;
+}
+```
+
+
+
Golang:
+
```golang
// 第一种二分法
func searchInsert(nums []int, target int) int {
diff --git a/problems/0077.组合.md b/problems/0077.组合.md
index 5a4811ba..17e4fb35 100644
--- a/problems/0077.组合.md
+++ b/problems/0077.组合.md
@@ -114,7 +114,7 @@ vector> result; // 存放符合条件结果的集合
vector path; // 用来存放符合条件结果
```
-其实不定义这两个全局遍历也是可以的,把这两个变量放进递归函数的参数里,但函数里参数太多影响可读性,所以我定义全局变量了。
+其实不定义这两个全局变量也是可以的,把这两个变量放进递归函数的参数里,但函数里参数太多影响可读性,所以我定义全局变量了。
函数里一定有两个参数,既然是集合n里面取k的数,那么n和k是两个int型的参数。
diff --git a/problems/0096.不同的二叉搜索树.md b/problems/0096.不同的二叉搜索树.md
index 9adc0457..51de1e23 100644
--- a/problems/0096.不同的二叉搜索树.md
+++ b/problems/0096.不同的二叉搜索树.md
@@ -252,6 +252,24 @@ function numTrees(n: number): number {
};
```
+### Rust
+
+```Rust
+impl Solution {
+ pub fn num_trees(n: i32) -> i32 {
+ let n = n as usize;
+ let mut dp = vec![0; n + 1];
+ dp[0] = 1;
+ for i in 1..=n {
+ for j in 1..=i {
+ dp[i] += dp[j - 1] * dp[i - j];
+ }
+ }
+ dp[n]
+ }
+}
+```
+
### C
```c
diff --git a/problems/0131.分割回文串.md b/problems/0131.分割回文串.md
index a54d6576..37132503 100644
--- a/problems/0131.分割回文串.md
+++ b/problems/0131.分割回文串.md
@@ -206,6 +206,65 @@ public:
return result;
}
};
+```
+# 优化
+
+上面的代码还存在一定的优化空间, 在于如何更高效的计算一个子字符串是否是回文字串。上述代码```isPalindrome```函数运用双指针的方法来判定对于一个字符串```s```, 给定起始下标和终止下标, 截取出的子字符串是否是回文字串。但是其中有一定的重复计算存在:
+
+例如给定字符串```"abcde"```, 在已知```"bcd"```不是回文字串时, 不再需要去双指针操作```"abcde"```而可以直接判定它一定不是回文字串。
+
+具体来说, 给定一个字符串`s`, 长度为```n```, 它成为回文字串的充分必要条件是```s[0] == s[n-1]```且```s[1:n-1]```是回文字串。
+
+大家如果熟悉动态规划这种算法的话, 我们可以高效地事先一次性计算出, 针对一个字符串```s```, 它的任何子串是否是回文字串, 然后在我们的回溯函数中直接查询即可, 省去了双指针移动判定这一步骤.
+
+具体参考代码如下:
+
+```CPP
+class Solution {
+private:
+ vector> result;
+ vector path; // 放已经回文的子串
+ vector> isPalindrome; // 放事先计算好的是否回文子串的结果
+ void backtracking (const string& s, int startIndex) {
+ // 如果起始位置已经大于s的大小,说明已经找到了一组分割方案了
+ if (startIndex >= s.size()) {
+ result.push_back(path);
+ return;
+ }
+ for (int i = startIndex; i < s.size(); i++) {
+ if (isPalindrome[startIndex][i]) { // 是回文子串
+ // 获取[startIndex,i]在s中的子串
+ string str = s.substr(startIndex, i - startIndex + 1);
+ path.push_back(str);
+ } else { // 不是回文,跳过
+ continue;
+ }
+ backtracking(s, i + 1); // 寻找i+1为起始位置的子串
+ path.pop_back(); // 回溯过程,弹出本次已经填在的子串
+ }
+ }
+ void computePalindrome(const string& s) {
+ // isPalindrome[i][j] 代表 s[i:j](双边包括)是否是回文字串
+ isPalindrome.resize(s.size(), vector(s.size(), false)); // 根据字符串s, 刷新布尔矩阵的大小
+ for (int i = s.size() - 1; i >= 0; i--) {
+ // 需要倒序计算, 保证在i行时, i+1行已经计算好了
+ for (int j = i; j < s.size(); j++) {
+ if (j == i) {isPalindrome[i][j] = true;}
+ else if (j - i == 1) {isPalindrome[i][j] = (s[i] == s[j]);}
+ else {isPalindrome[i][j] = (s[i] == s[j] && isPalindrome[i+1][j-1]);}
+ }
+ }
+ }
+public:
+ vector> partition(string s) {
+ result.clear();
+ path.clear();
+ computePalindrome(s);
+ backtracking(s, 0);
+ return result;
+ }
+};
+
```
# 总结
diff --git a/problems/0150.逆波兰表达式求值.md b/problems/0150.逆波兰表达式求值.md
index 21bd8593..8107e4e0 100644
--- a/problems/0150.逆波兰表达式求值.md
+++ b/problems/0150.逆波兰表达式求值.md
@@ -65,6 +65,8 @@
# 思路
+《代码随想录》算法视频公开课:[栈的最后表演! | LeetCode:150. 逆波兰表达式求值](https://www.bilibili.com/video/BV1kd4y1o7on),相信结合视频在看本篇题解,更有助于大家对本题的理解。
+
在上一篇文章中[1047.删除字符串中的所有相邻重复项](https://programmercarl.com/1047.删除字符串中的所有相邻重复项.html)提到了 递归就是用栈来实现的。
所以**栈与递归之间在某种程度上是可以转换的!** 这一点我们在后续讲解二叉树的时候,会更详细的讲解到。
diff --git a/problems/0239.滑动窗口最大值.md b/problems/0239.滑动窗口最大值.md
index 6ec98506..3f402f12 100644
--- a/problems/0239.滑动窗口最大值.md
+++ b/problems/0239.滑动窗口最大值.md
@@ -32,6 +32,8 @@
# 思路
+《代码随想录》算法视频公开课:[单调队列正式登场!| LeetCode:239. 滑动窗口最大值](https://www.bilibili.com/video/BV1XS4y1p7qj),相信结合视频在看本篇题解,更有助于大家对本题的理解。
+
这是使用单调队列的经典题目。
难点是如何求一个区间里的最大值呢? (这好像是废话),暴力一下不就得了。
diff --git a/problems/0343.整数拆分.md b/problems/0343.整数拆分.md
index a4d532fd..0a568b57 100644
--- a/problems/0343.整数拆分.md
+++ b/problems/0343.整数拆分.md
@@ -192,7 +192,7 @@ public:
## 其他语言版本
-### Java
+### Java
```Java
class Solution {
public int integerBreak(int n) {
@@ -259,6 +259,21 @@ func max(a,b int) int{
}
```
+### Rust
+```rust
+pub fn integer_break(n: i32) -> i32 {
+ let n = n as usize;
+ let mut dp = vec![0; n + 1];
+ dp[2] = 1;
+ for i in 3..=n {
+ for j in 1..i-1 {
+ dp[i] = dp[i].max((i - j) * j).max(dp[i - j] * j);
+ }
+ }
+ dp[n] as i32
+}
+```
+
### Javascript
```Javascript
var integerBreak = function(n) {
@@ -299,6 +314,27 @@ function integerBreak(n: number): number {
};
```
+### Rust
+
+```Rust
+impl Solution {
+ fn max(a: i32, b: i32) -> i32{
+ if a > b { a } else { b }
+ }
+ pub fn integer_break(n: i32) -> i32 {
+ let n = n as usize;
+ let mut dp = vec![0; n + 1];
+ dp[2] = 1;
+ for i in 3..=n {
+ for j in 1..i - 1 {
+ dp[i] = Self::max(dp[i], Self::max(((i - j) * j) as i32, dp[i - j] * j as i32));
+ }
+ }
+ dp[n]
+ }
+}
+```
+
### C
```c
diff --git a/problems/0347.前K个高频元素.md b/problems/0347.前K个高频元素.md
index 430dcea1..d4059b9b 100644
--- a/problems/0347.前K个高频元素.md
+++ b/problems/0347.前K个高频元素.md
@@ -31,6 +31,14 @@
# 思路
+《代码随想录》算法视频公开课:[优先级队列正式登场!大顶堆、小顶堆该怎么用?| LeetCode:347.前 K 个高频元素](https://www.bilibili.com/video/BV1Xg41167Lz),相信结合视频在看本篇题解,更有助于大家对本题的理解。
+
+
+
+
+
+
+
这道题目主要涉及到如下三块内容:
1. 要统计元素出现频率
2. 对频率排序
diff --git a/problems/0376.摆动序列.md b/problems/0376.摆动序列.md
index a41a0f0a..d15ed2d0 100644
--- a/problems/0376.摆动序列.md
+++ b/problems/0376.摆动序列.md
@@ -266,22 +266,58 @@ class Solution:
### Go
+**贪心**
```golang
func wiggleMaxLength(nums []int) int {
- var count,preDiff,curDiff int
- count=1
- if len(nums)<2{
- return count
- }
- for i:=0;i 0 && preDiff <= 0) || (preDiff >= 0 && curDiff < 0){
- preDiff=curDiff
- count++
- }
- }
- return count
+ var count, preDiff, curDiff int //初始化默认为0
+ count = 1 // 初始化为1,因为最小的序列是1个数
+ if len(nums) < 2 {
+ return count
+ }
+ for i := 0; i < len(nums)-1; i++ {
+ curDiff = nums[i+1] - nums[i]
+ if (curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0) {
+ count++
+ }
+ }
+ return count
+}
+```
+
+**动态规划**
+```golang
+func wiggleMaxLength(nums []int) int {
+ n := len(nums)
+ if n <= 1 {
+ return n
+ }
+ dp := make([][2]int, n)
+ // i 0 作为波峰的最大长度
+ // i 1 作为波谷的最大长度
+ dp[0][0] = 1
+ dp[0][1] = 1
+ for i := 0; i < n; i++ {
+ for j := 0; j < i; j++ {
+ if nums[j] > nums[i] { //nums[i]为波谷
+ dp[i][1] = max(dp[i][1], dp[j][0]+1)
+ }
+ if nums[j] < nums[i] { //nums[i]为波峰 或者相等
+ dp[i][0] = max(dp[i][0], dp[j][1]+1)
+ }
+ if nums[j] == nums[i] { //添加一种情况,nums[i]为相等
+ dp[i][0] = max(dp[i][0], dp[j][0]) //波峰
+ dp[i][1] = max(dp[i][1], dp[j][1]) //波谷
+ }
+ }
+ }
+ return max(dp[n-1][0], dp[n-1][1])
+}
+func max(a, b int) int {
+ if a > b {
+ return a
+ } else {
+ return b
+ }
}
```
diff --git a/problems/0416.分割等和子集.md b/problems/0416.分割等和子集.md
index 83b267ac..03eae8ef 100644
--- a/problems/0416.分割等和子集.md
+++ b/problems/0416.分割等和子集.md
@@ -417,7 +417,32 @@ var canPartition = function(nums) {
```
+### Rust
+```Rust
+impl Solution {
+ fn max(a: usize, b: usize) -> usize {
+ if a > b { a } else { b }
+ }
+ pub fn can_partition(nums: Vec) -> bool {
+ let nums = nums.iter().map(|x| *x as usize).collect::>();
+ let mut sum = 0;
+ let mut dp: Vec = vec![0; 10001];
+ for i in 0..nums.len() {
+ sum += nums[i];
+ }
+ if sum % 2 == 1 { return false; }
+ let target = sum / 2;
+ for i in 0..nums.len() {
+ for j in (nums[i]..=target).rev() {
+ dp[j] = Self::max(dp[j], dp[j - nums[i]] + nums[i]);
+ }
+ }
+ if dp[target] == target { return true; }
+ false
+ }
+}
+```
### C:
diff --git a/problems/0695.岛屿的最大面积.md b/problems/0695.岛屿的最大面积.md
index b0945292..3739882a 100644
--- a/problems/0695.岛屿的最大面积.md
+++ b/problems/0695.岛屿的最大面积.md
@@ -16,6 +16,17 @@
# 思路
+这道题目也是 dfs bfs基础类题目。
+
+
+## DFS
+
+很多同学,写dfs其实也是凭感觉来,有的时候dfs函数中写终止条件才能过,有的时候 dfs函数不写终止添加也能过!
+
+这里其实涉及到dfs的两种写法,
+
+以下代码使用dfs实现,如果对dfs不太了解的话,建议先看这篇题解:[797.所有可能的路径](https://leetcode.cn/problems/all-paths-from-source-to-target/solution/by-carlsun-2-66pf/),
+
写法一,dfs只处理下一个节点
```CPP
class Solution {
@@ -94,3 +105,55 @@ public:
}
};
```
+
+以上两种写法的区别,我在题解: [DFS,BDF 你没注意的细节都给你列出来了!LeetCode:200. 岛屿数量](https://leetcode.cn/problems/number-of-islands/solution/by-carlsun-2-n72a/)做了详细介绍。
+
+## BFS
+
+```CPP
+class Solution {
+private:
+ int count;
+ int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 四个方向
+ void bfs(vector>& grid, vector>& visited, int x, int y) {
+ queue que;
+ que.push(x);
+ que.push(y);
+ visited[x][y] = true; // 加入队列就意味节点是陆地可到达的点
+ count++;
+ while(!que.empty()) {
+ int xx = que.front();que.pop();
+ int yy = que.front();que.pop();
+ for (int i = 0 ;i < 4; i++) {
+ int nextx = xx + dir[i][0];
+ int nexty = yy + dir[i][1];
+ if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue; // 越界
+ if (!visited[nextx][nexty] && grid[nextx][nexty] == 1) { // 节点没有被访问过且是陆地
+ visited[nextx][nexty] = true;
+ count++;
+ que.push(nextx);
+ que.push(nexty);
+ }
+ }
+ }
+ }
+
+public:
+ int maxAreaOfIsland(vector>& grid) {
+ int n = grid.size(), m = grid[0].size();
+ vector> visited = vector>(n, vector(m, false));
+ int result = 0;
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < m; j++) {
+ if (!visited[i][j] && grid[i][j] == 1) {
+ count = 0;
+ bfs(grid, visited, i, j); // 将与其链接的陆地都标记上 true
+ result = max(result, count);
+ }
+ }
+ }
+ return result;
+ }
+};
+
+```
diff --git a/problems/0704.二分查找.md b/problems/0704.二分查找.md
index eec97a78..53f5331a 100644
--- a/problems/0704.二分查找.md
+++ b/problems/0704.二分查找.md
@@ -290,10 +290,11 @@ func search(nums []int, target int) int {
*/
var search = function(nums, target) {
// right是数组最后一个数的下标,num[right]在查找范围内,是左闭右闭区间
- let left = 0, right = nums.length - 1;
+ let mid, left = 0, right = nums.length - 1;
// 当left=right时,由于nums[right]在查找范围内,所以要包括此情况
while (left <= right) {
- let mid = left + Math.floor((right - left)/2);
+ // 位运算 + 防止大数溢出
+ mid = left + ((right - left) >> 1);
// 如果中间数大于目标值,要把中间数排除查找范围,所以右边界更新为mid-1;如果右边界更新为mid,那中间数还在下次查找范围内
if (nums[mid] > target) {
right = mid - 1; // 去左面闭区间寻找
@@ -316,10 +317,11 @@ var search = function(nums, target) {
*/
var search = function(nums, target) {
// right是数组最后一个数的下标+1,nums[right]不在查找范围内,是左闭右开区间
- let left = 0, right = nums.length;
+ let mid, left = 0, right = nums.length;
// 当left=right时,由于nums[right]不在查找范围,所以不必包括此情况
while (left < right) {
- let mid = left + Math.floor((right - left)/2);
+ // 位运算 + 防止大数溢出
+ mid = left + ((right - left) >> 1);
// 如果中间值大于目标值,中间值不应在下次查找的范围内,但中间值的前一个值应在;
// 由于right本来就不在查找范围内,所以将右边界更新为中间值,如果更新右边界为mid-1则将中间值的前一个值也踢出了下次寻找范围
if (nums[mid] > target) {
@@ -340,9 +342,10 @@ var search = function(nums, target) {
```typescript
function search(nums: number[], target: number): number {
- let left: number = 0, right: number = nums.length - 1;
+ let mid: number, left: number = 0, right: number = nums.length - 1;
while (left <= right) {
- let mid: number = left + Math.floor((right - left) / 2);
+ // 位运算 + 防止大数溢出
+ mid = left + ((right - left) >> 1);
if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] < target) {
@@ -359,9 +362,10 @@ function search(nums: number[], target: number): number {
```typescript
function search(nums: number[], target: number): number {
- let left: number = 0, right: number = nums.length;
+ let mid: number, left: number = 0, right: number = nums.length;
while (left < right) {
- let mid: number = left + Math.floor((right - left) / 2);
+ // 位运算 + 防止大数溢出
+ mid = left +((right - left) >> 1);
if (nums[mid] > target) {
right = mid;
} else if (nums[mid] < target) {
diff --git a/problems/0922.按奇偶排序数组II.md b/problems/0922.按奇偶排序数组II.md
index 49547a15..4e281a3c 100644
--- a/problems/0922.按奇偶排序数组II.md
+++ b/problems/0922.按奇偶排序数组II.md
@@ -147,6 +147,59 @@ class Solution {
}
```
+### java
+
+```java
+//方法一:采用额外的数组空间
+class Solution {
+ public int[] sortArrayByParityII(int[] nums) {
+ //定义结果数组 result
+ int[] result = new int[nums.length];
+ int even = 0, odd = 1;
+ for(int i = 0; i < nums.length; i++){
+ //如果为偶数
+ if(nums[i] % 2 == 0){
+ result[even] = nums[i];
+ even += 2;
+ }else{
+ result[odd] = nums[i];
+ odd += 2;
+ }
+ }
+ return result;
+ }
+}
+```
+```java
+//方法二:不采用额外的数组空间
+class Solution922 {
+ public int[] sortArrayByParityII(int[] nums) {
+ //定义双指针
+ int oddPoint = 1, evenPoint = 0;
+ //开始移动并交换,最后一层必然为相互交换后再移动或者相同直接移动
+ while(oddPoint < nums.length && evenPoint < nums.length){
+ //进行判断
+ if(nums[oddPoint] % 2 == 0 && nums[evenPoint] % 2 == 1){ //如果均不满足
+ int temp = 0;
+ temp = nums[oddPoint];
+ nums[oddPoint] = nums[evenPoint];
+ nums[evenPoint] = temp;
+ oddPoint += 2;
+ evenPoint += 2;
+ }else if(nums[oddPoint] % 2 == 0 && nums[evenPoint] % 2 == 0){ //偶数满足
+ evenPoint += 2;
+ }else if(nums[oddPoint] % 2 == 1 && nums[evenPoint] % 2 == 1){ //奇数满足
+ oddPoint += 2;
+ }else{
+ oddPoint += 2;
+ evenPoint += 2;
+ }
+ }
+ return nums;
+ }
+}
+```
+
### Python3
```python
diff --git a/problems/面试题02.07.链表相交.md b/problems/面试题02.07.链表相交.md
index abf7a2f8..6d6810a3 100644
--- a/problems/面试题02.07.链表相交.md
+++ b/problems/面试题02.07.链表相交.md
@@ -5,7 +5,9 @@
参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!
-# 面试题 02.07. 链表相交
+# 面试题 02.07. 链表相交
+
+同:160.链表相交
[力扣题目链接](https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/)
diff --git a/添加0222.完全二叉树的节点个数Go版本.md b/添加0222.完全二叉树的节点个数Go版本.md
new file mode 100644
index 00000000..6001e7b7
--- /dev/null
+++ b/添加0222.完全二叉树的节点个数Go版本.md
@@ -0,0 +1,25 @@
+```go
+func countNodes(root *TreeNode) int {
+ if root == nil {
+ return 0
+ }
+ q := list.New()
+ q.PushBack(root)
+ res := 0
+ for q.Len() > 0 {
+ n := q.Len()
+ for i := 0; i < n; i++ {
+ node := q.Remove(q.Front()).(*TreeNode)
+ if node.Left != nil {
+ q.PushBack(node.Left)
+ }
+ if node.Right != nil {
+ q.PushBack(node.Right)
+ }
+ res++
+ }
+ }
+ return res
+}
+```
+
diff --git a/添加559.n叉树的最大深度Go版本.md b/添加559.n叉树的最大深度Go版本.md
new file mode 100644
index 00000000..3172837d
--- /dev/null
+++ b/添加559.n叉树的最大深度Go版本.md
@@ -0,0 +1,22 @@
+```go
+func maxDepth(root *Node) int {
+ if root == nil {
+ return 0
+ }
+ q := list.New()
+ q.PushBack(root)
+ depth := 0
+ for q.Len() > 0 {
+ n := q.Len()
+ for i := 0; i < n; i++ {
+ node := q.Remove(q.Front()).(*Node)
+ for j := range node.Children {
+ q.PushBack(node.Children[j])
+ }
+ }
+ depth++
+ }
+ return depth
+}
+```
+