diff --git a/problems/0005.最长回文子串.md b/problems/0005.最长回文子串.md
index 30851a46..cb022ac3 100644
--- a/problems/0005.最长回文子串.md
+++ b/problems/0005.最长回文子串.md
@@ -263,6 +263,32 @@ public:
## Java
```java
+// 双指针 中心扩散法
+class Solution {
+ public String longestPalindrome(String s) {
+ String s1 = "";
+ String s2 = "";
+ String res = "";
+ for (int i = 0; i < s.length(); i++) {
+ // 分两种情况:即一个元素作为中心点,两个元素作为中心点
+ s1 = extend(s, i, i); // 情况1
+ res = s1.length() > res.length() ? s1 : res;
+ s2 = extend(s, i, i + 1); // 情况2
+ res = s2.length() > res.length() ? s2 : res;
+ }
+ return res; // 返回最长的
+ }
+ public String extend(String s, int start, int end){
+ String tmp = "";
+ while (start >= 0 && end < s.length() && s.charAt(start) == s.charAt(end)){
+ tmp = s.substring(start, end + 1); // Java中substring是左闭右开的,所以要+1
+ // 向两边扩散
+ start--;
+ end++;
+ }
+ return tmp;
+ }
+}
```
## Python
@@ -317,6 +343,7 @@ class Solution:
## Go
```go
+
```
## JavaScript
diff --git a/problems/0028.实现strStr.md b/problems/0028.实现strStr.md
index c70d522e..1c654dd4 100644
--- a/problems/0028.实现strStr.md
+++ b/problems/0028.实现strStr.md
@@ -118,7 +118,7 @@ next数组就是一个前缀表(prefix table)。
此时就要问了**前缀表是如何记录的呢?**
-首先要知道前缀表的任务是当前位置匹配失败,找到之前已经匹配上的位置,在重新匹配,此也意味着在某个字符失配时,前缀表会告诉你下一步匹配中,模式串应该跳到哪个位置。
+首先要知道前缀表的任务是当前位置匹配失败,找到之前已经匹配上的位置,再重新匹配,此也意味着在某个字符失配时,前缀表会告诉你下一步匹配中,模式串应该跳到哪个位置。
那么什么是前缀表:**记录下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀。**
@@ -146,7 +146,7 @@ next数组就是一个前缀表(prefix table)。
# 为什么一定要用前缀表
-这就是前缀表那为啥就能告诉我们 上次匹配的位置,并跳过去呢?
+这就是前缀表,那为啥就能告诉我们 上次匹配的位置,并跳过去呢?
回顾一下,刚刚匹配的过程在下标5的地方遇到不匹配,模式串是指向f,如图:
diff --git a/problems/0031.下一个排列.md b/problems/0031.下一个排列.md
index 3db099fe..2dad8b27 100644
--- a/problems/0031.下一个排列.md
+++ b/problems/0031.下一个排列.md
@@ -163,6 +163,29 @@ class Solution:
low += 1
high -= 1
```
+>上一版本简化版
+'''python
+class Solution(object):
+ def nextPermutation(self, nums: List[int]) -> None:
+ n = len(nums)
+ i = n-2
+ while i >= 0 and nums[i] >= nums[i+1]:
+ i -= 1
+
+ if i > -1: // i==-1,不存在下一个更大的排列
+ j = n-1
+ while j >= 0 and nums[j] <= nums[i]:
+ j -= 1
+ nums[i], nums[j] = nums[j], nums[i]
+
+ start, end = i+1, n-1
+ while start < end:
+ nums[start], nums[end] = nums[end], nums[start]
+ start += 1
+ end -= 1
+
+ return nums
+'''
## Go
diff --git a/problems/0042.接雨水.md b/problems/0042.接雨水.md
index 5caddfaa..3c1577a8 100644
--- a/problems/0042.接雨水.md
+++ b/problems/0042.接雨水.md
@@ -602,7 +602,48 @@ func trap(height []int) int {
}
```
+动态规划解法:
+
+```go
+func trap(height []int) int {
+ sum:=0
+ n:=len(height)
+ lh:=make([]int,n)
+ rh:=make([]int,n)
+ lh[0]=height[0]
+ rh[n-1]=height[n-1]
+ for i:=1;i=0;i--{
+ rh[i]=max(rh[i+1],height[i])
+ }
+ for i:=1;i0{
+ sum+=h
+ }
+ }
+ return sum
+}
+func max(a,b int)int{
+ if a>b{
+ return a
+ }
+ return b
+}
+func min(a,b int)int{
+ if aleft);
+ //求出右子树深度
+ int right = maxDepth(root->right);
+ //求出左子树深度和右子树深度的较大值
+ int max = left > right ? left : right;
+ //返回较大值+1(1为当前层数)
+ return max + 1;
+}
+```
+二叉树最大深度迭代
+```c
+int maxDepth(struct TreeNode* root){
+ //若传入根节点为NULL,返回0
+ if(!root)
+ return 0;
+
+ int depth = 0;
+ //开辟队列空间
+ struct TreeNode** queue = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 6000);
+ int queueFront = 0;
+ int queueEnd = 0;
+
+ //将根结点入队
+ queue[queueEnd++] = root;
+
+ int queueSize;
+ //求出当前队列中元素个数
+ while(queueSize = queueEnd - queueFront) {
+ int i;
+ //若当前队列中结点有左右子树,则将它们的左右子树入队
+ for(i = 0; i < queueSize; i++) {
+ struct TreeNode* tempNode = queue[queueFront + i];
+ if(tempNode->left)
+ queue[queueEnd++] = tempNode->left;
+ if(tempNode->right)
+ queue[queueEnd++] = tempNode->right;
+ }
+ //更新队头下标
+ queueFront += queueSize;
+ //深度+1
+ depth++;
+ }
+ return depth;
+}
+```
+
-----------------------
diff --git a/problems/0122.买卖股票的最佳时机II(动态规划).md b/problems/0122.买卖股票的最佳时机II(动态规划).md
index 7cd6c0ad..e701a821 100644
--- a/problems/0122.买卖股票的最佳时机II(动态规划).md
+++ b/problems/0122.买卖股票的最佳时机II(动态规划).md
@@ -197,6 +197,33 @@ class Solution:
```
Go:
+```go
+// 买卖股票的最佳时机Ⅱ 动态规划
+// 时间复杂度O(n) 空间复杂度O(n)
+func maxProfit(prices []int) int {
+ dp := make([][]int, len(prices))
+ status := make([]int, len(prices) * 2)
+ for i := range dp {
+ dp[i] = status[:2]
+ status = status[2:]
+ }
+ dp[0][0] = -prices[0]
+
+ for i := 1; i < len(prices); i++ {
+ dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i])
+ dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i])
+ }
+
+ return dp[len(prices) - 1][1]
+}
+
+func max(a, b int) int {
+ if a > b {
+ return a
+ }
+ return b
+}
+```
```go
func maxProfit(prices []int) int {
diff --git a/problems/0123.买卖股票的最佳时机III.md b/problems/0123.买卖股票的最佳时机III.md
index 47a30ab9..9c269978 100644
--- a/problems/0123.买卖股票的最佳时机III.md
+++ b/problems/0123.买卖股票的最佳时机III.md
@@ -347,7 +347,38 @@ const maxProfit = prices => {
};
```
+Go:
+> 版本一:
+```go
+// 买卖股票的最佳时机III 动态规划
+// 时间复杂度O(n) 空间复杂度O(n)
+func maxProfit(prices []int) int {
+ dp := make([][]int, len(prices))
+ status := make([]int, len(prices) * 4)
+ for i := range dp {
+ dp[i] = status[:4]
+ status = status[4:]
+ }
+ dp[0][0], dp[0][2] = -prices[0], -prices[0]
+
+ for i := 1; i < len(prices); i++ {
+ dp[i][0] = max(dp[i - 1][0], -prices[i])
+ dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i])
+ dp[i][2] = max(dp[i - 1][2], dp[i - 1][1] - prices[i])
+ dp[i][3] = max(dp[i - 1][3], dp[i - 1][2] + prices[i])
+ }
+
+ return dp[len(prices) - 1][3]
+}
+
+func max(a, b int) int {
+ if a > b {
+ return a
+ }
+ return b
+}
+```
-----------------------
diff --git a/problems/0188.买卖股票的最佳时机IV.md b/problems/0188.买卖股票的最佳时机IV.md
index 22a1a141..73861b35 100644
--- a/problems/0188.买卖股票的最佳时机IV.md
+++ b/problems/0188.买卖股票的最佳时机IV.md
@@ -273,6 +273,41 @@ class Solution:
return dp[2*k]
```
Go:
+版本一:
+```go
+// 买卖股票的最佳时机IV 动态规划
+// 时间复杂度O(kn) 空间复杂度O(kn)
+func maxProfit(k int, prices []int) int {
+ if k == 0 || len(prices) == 0 {
+ return 0
+ }
+
+ dp := make([][]int, len(prices))
+ status := make([]int, (2 * k + 1) * len(prices))
+ for i := range dp {
+ dp[i] = status[:2 * k + 1]
+ status = status[2 * k + 1:]
+ }
+ for j := 1; j < 2 * k; j += 2 {
+ dp[0][j] = -prices[0]
+ }
+
+ for i := 1; i < len(prices); i++ {
+ for j := 0; j < 2 * k; j += 2 {
+ dp[i][j + 1] = max(dp[i - 1][j + 1], dp[i - 1][j] - prices[i])
+ dp[i][j + 2] = max(dp[i - 1][j + 2], dp[i - 1][j + 1] + prices[i])
+ }
+ }
+ return dp[len(prices) - 1][2 * k]
+}
+
+func max(a, b int) int {
+ if a > b {
+ return a
+ }
+ return b
+}
+```
```go
func maxProfit(k int, prices []int) int {
diff --git a/problems/0222.完全二叉树的节点个数.md b/problems/0222.完全二叉树的节点个数.md
index 56052b52..2e964dfc 100644
--- a/problems/0222.完全二叉树的节点个数.md
+++ b/problems/0222.完全二叉树的节点个数.md
@@ -447,7 +447,80 @@ var countNodes = function(root) {
};
```
+## C:
+递归法
+```c
+int countNodes(struct TreeNode* root) {
+ //若传入结点不存在,返回0
+ if(!root)
+ return 0;
+ //算出左右子树的结点总数
+ int leftCount = countNodes(root->left);
+ int rightCount = countNodes(root->right);
+ //返回左右子树结点总数+1
+ return leftCount + rightCount + 1;
+}
+int countNodes(struct TreeNode* root){
+ return getNodes(root);
+}
+```
+
+迭代法
+```c
+int countNodes(struct TreeNode* root){
+ //记录结点总数
+ int totalNum = 0;
+ //开辟栈空间
+ struct TreeNode** stack = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 100);
+ int stackTop = 0;
+ //如果root结点不为NULL,则将其入栈。若为NULL,则不会进入遍历,返回0
+ if(root)
+ stack[stackTop++] = root;
+ //若栈中有结点存在,则进行遍历
+ while(stackTop) {
+ //取出栈顶元素
+ struct TreeNode* tempNode = stack[--stackTop];
+ //结点总数+1
+ totalNum++;
+ //若栈顶结点有左右孩子,将它们入栈
+ if(tempNode->left)
+ stack[stackTop++] = tempNode->left;
+ if(tempNode->right)
+ stack[stackTop++] = tempNode->right;
+ }
+ return totalNum;
+}
+```
+
+满二叉树
+```c
+int countNodes(struct TreeNode* root){
+ if(!root)
+ return 0;
+ int leftHeight = 0;
+ int rightHeight = 0;
+ struct TreeNode* rightNode = root->right;
+ struct TreeNode* leftNode = root->left;
+ //求出左子树深度
+ while(leftNode) {
+ leftNode = leftNode->left;
+ leftHeight++;
+ }
+
+ //求出右子树深度
+ while(rightNode) {
+ rightNode = rightNode->right;
+ rightHeight++;
+ }
+ //若左右子树深度相同,为满二叉树。结点个数为2^height-1
+ if(rightHeight == leftHeight) {
+ return (2 << leftHeight) - 1;
+ }
+ //否则返回左右子树的结点个数+1
+ return countNodes(root->right) + countNodes(root->left) + 1;
+}
+```
-----------------------
diff --git a/problems/0226.翻转二叉树.md b/problems/0226.翻转二叉树.md
index 00f0e1c0..12c60c7e 100644
--- a/problems/0226.翻转二叉树.md
+++ b/problems/0226.翻转二叉树.md
@@ -563,7 +563,7 @@ var invertTree = function(root) {
};
```
-C:
+### C:
递归法
```c
struct TreeNode* invertTree(struct TreeNode* root){
@@ -580,6 +580,7 @@ struct TreeNode* invertTree(struct TreeNode* root){
return root;
}
```
+
迭代法:深度优先遍历
```c
struct TreeNode* invertTree(struct TreeNode* root){
diff --git a/problems/0239.滑动窗口最大值.md b/problems/0239.滑动窗口最大值.md
index 5a910908..8a8d3a52 100644
--- a/problems/0239.滑动窗口最大值.md
+++ b/problems/0239.滑动窗口最大值.md
@@ -408,7 +408,7 @@ var maxSlidingWindow = function (nums, k) {
// 入队当前元素下标
q.push(i);
// 判断当前最大值(即队首元素)是否在窗口中,若不在便将其出队
- while (q[0] <= i - k) {
+ if (q[0] <= i - k) {
q.shift();
}
// 当达到窗口大小时便开始向结果中添加数据
diff --git a/problems/0309.最佳买卖股票时机含冷冻期.md b/problems/0309.最佳买卖股票时机含冷冻期.md
index e6c6839a..8520e655 100644
--- a/problems/0309.最佳买卖股票时机含冷冻期.md
+++ b/problems/0309.最佳买卖股票时机含冷冻期.md
@@ -205,6 +205,40 @@ class Solution:
```
Go:
+```go
+// 最佳买卖股票时机含冷冻期 动态规划
+// 时间复杂度O(n) 空间复杂度O(n)
+func maxProfit(prices []int) int {
+ n := len(prices)
+ if n < 2 {
+ return 0
+ }
+
+ dp := make([][]int, n)
+ status := make([]int, n * 4)
+ for i := range dp {
+ dp[i] = status[:4]
+ status = status[4:]
+ }
+ dp[0][0] = -prices[0]
+
+ for i := 1; i < n; i++ {
+ dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][1] - prices[i], dp[i - 1][3] - prices[i]))
+ dp[i][1] = max(dp[i - 1][1], dp[i - 1][3])
+ dp[i][2] = dp[i - 1][0] + prices[i]
+ dp[i][3] = dp[i - 1][2]
+ }
+
+ return max(dp[n - 1][1], max(dp[n - 1][2], dp[n - 1][3]))
+}
+
+func max(a, b int) int {
+ if a > b {
+ return a
+ }
+ return b
+}
+```
Javascript:
diff --git a/problems/0463.岛屿的周长.md b/problems/0463.岛屿的周长.md
index 65783cc3..39808e0e 100644
--- a/problems/0463.岛屿的周长.md
+++ b/problems/0463.岛屿的周长.md
@@ -121,6 +121,41 @@ class Solution {
```
Python:
+### 解法1:
+扫描每个cell,如果当前位置为岛屿 grid[i][j] == 1, 从当前位置判断四边方向,如果边界或者是水域,证明有边界存在,res矩阵的对应cell加一。
+
+```python3
+class Solution:
+ def islandPerimeter(self, grid: List[List[int]]) -> int:
+
+ m = len(grid)
+ n = len(grid[0])
+
+ # 创建res二维素组记录答案
+ res = [[0] * n for j in range(m)]
+
+ for i in range(m):
+ for j in range(len(grid[i])):
+ # 如果当前位置为水域,不做修改或reset res[i][j] = 0
+ if grid[i][j] == 0:
+ res[i][j] = 0
+ # 如果当前位置为陆地,往四个方向判断,update res[i][j]
+ elif grid[i][j] == 1:
+ if i == 0 or (i > 0 and grid[i-1][j] == 0):
+ res[i][j] += 1
+ if j == 0 or (j >0 and grid[i][j-1] == 0):
+ res[i][j] += 1
+ if i == m-1 or (i < m-1 and grid[i+1][j] == 0):
+ res[i][j] += 1
+ if j == n-1 or (j < n-1 and grid[i][j+1] == 0):
+ res[i][j] += 1
+
+ # 最后求和res矩阵,这里其实不一定需要矩阵记录,可以设置一个variable res 记录边长,舍矩阵无非是更加形象而已
+ ans = sum([sum(row) for row in res])
+
+ return ans
+
+```
Go:
diff --git a/problems/0654.最大二叉树.md b/problems/0654.最大二叉树.md
index 89cc4927..af945aca 100644
--- a/problems/0654.最大二叉树.md
+++ b/problems/0654.最大二叉树.md
@@ -354,6 +354,35 @@ var constructMaximumBinaryTree = function (nums) {
};
```
+## C
+```c
+struct TreeNode* traversal(int* nums, int left, int right) {
+ //若左边界大于右边界,返回NULL
+ if(left >= right)
+ return NULL;
+
+ //找出数组中最大数坐标
+ int maxIndex = left;
+ int i;
+ for(i = left + 1; i < right; i++) {
+ if(nums[i] > nums[maxIndex])
+ maxIndex = i;
+ }
+
+ //开辟结点
+ struct TreeNode* node = (struct TreeNode*)malloc(sizeof(struct TreeNode));
+ //将结点的值设为最大数组数组元素
+ node->val = nums[maxIndex];
+ //递归定义左孩子结点和右孩子结点
+ node->left = traversal(nums, left, maxIndex);
+ node->right = traversal(nums, maxIndex + 1, right);
+ return node;
+}
+
+struct TreeNode* constructMaximumBinaryTree(int* nums, int numsSize){
+ return traversal(nums, 0, numsSize);
+}
+```
-----------------------
diff --git a/problems/0669.修剪二叉搜索树.md b/problems/0669.修剪二叉搜索树.md
index f6ae146a..89096320 100644
--- a/problems/0669.修剪二叉搜索树.md
+++ b/problems/0669.修剪二叉搜索树.md
@@ -139,7 +139,7 @@ if (root->val < low) {
root->left = trimBST(root->left, low, high);
```
-此时节点3的右孩子就变成了节点2,将节点0从二叉树中移除了。
+此时节点3的左孩子就变成了节点2,将节点0从二叉树中移除了。
最后整体代码如下:
diff --git a/problems/0714.买卖股票的最佳时机含手续费(动态规划).md b/problems/0714.买卖股票的最佳时机含手续费(动态规划).md
index b64d91d2..2b3416d4 100644
--- a/problems/0714.买卖股票的最佳时机含手续费(动态规划).md
+++ b/problems/0714.买卖股票的最佳时机含手续费(动态规划).md
@@ -150,14 +150,16 @@ class Solution:
```
Go:
-```Go
+```go
+// 买卖股票的最佳时机含手续费 动态规划
+// 时间复杂度O(n) 空间复杂度O(n)
func maxProfit(prices []int, fee int) int {
n := len(prices)
dp := make([][2]int, n)
dp[0][0] = -prices[0]
for i := 1; i < n; i++ {
- dp[i][1] = max(dp[i-1][1], dp[i-1][0]+prices[i]-fee)
- dp[i][0] = max(dp[i-1][0], dp[i-1][1]-prices[i])
+ dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i] - fee)
+ dp[i][0] = max(dp[i-1][0], dp[i-1][1] - prices[i])
}
return dp[n-1][1]
}
diff --git a/problems/1047.删除字符串中的所有相邻重复项.md b/problems/1047.删除字符串中的所有相邻重复项.md
index 91885f8d..66f34978 100644
--- a/problems/1047.删除字符串中的所有相邻重复项.md
+++ b/problems/1047.删除字符串中的所有相邻重复项.md
@@ -267,6 +267,57 @@ var removeDuplicates = function(s) {
};
```
+C:
+方法一:使用栈
+```c
+char * removeDuplicates(char * s){
+ //求出字符串长度
+ int strLength = strlen(s);
+ //开辟栈空间。栈空间长度应为字符串长度+1(为了存放字符串结束标志'\0')
+ char* stack = (char*)malloc(sizeof(char) * strLength + 1);
+ int stackTop = 0;
+
+ int index = 0;
+ //遍历整个字符串
+ while(index < strLength) {
+ //取出当前index对应字母,之后index+1
+ char letter = s[index++];
+ //若栈中有元素,且栈顶字母等于当前字母(两字母相邻)。将栈顶元素弹出
+ if(stackTop > 0 && letter == stack[stackTop - 1])
+ stackTop--;
+ //否则将字母入栈
+ else
+ stack[stackTop++] = letter;
+ }
+ //存放字符串结束标志'\0'
+ stack[stackTop] = '\0';
+ //返回栈本身作为字符串
+ return stack;
+}
+```
+方法二:双指针法
+```c
+char * removeDuplicates(char * s){
+ //创建快慢指针
+ int fast = 0;
+ int slow = 0;
+ //求出字符串长度
+ int strLength = strlen(s);
+ //遍历字符串
+ while(fast < strLength) {
+ //将当前slow指向字符改为fast指向字符。fast指针+1
+ char letter = s[slow] = s[fast++];
+ //若慢指针大于0,且慢指针指向元素等于字符串中前一位元素,删除慢指针指向当前元素
+ if(slow > 0 && letter == s[slow - 1])
+ slow--;
+ else
+ slow++;
+ }
+ //在字符串结束加入字符串结束标志'\0'
+ s[slow] = 0;
+ return s;
+}
+```
-----------------------
diff --git a/problems/1365.有多少小于当前数字的数字.md b/problems/1365.有多少小于当前数字的数字.md
index a2592957..5e1e875c 100644
--- a/problems/1365.有多少小于当前数字的数字.md
+++ b/problems/1365.有多少小于当前数字的数字.md
@@ -150,7 +150,35 @@ class Solution:
res[i] = hash[num]
return res
```
+
Go:
+```go
+func smallerNumbersThanCurrent(nums []int) []int {
+ // map,key[数组中出现的数] value[比这个数小的个数]
+ m := make(map[int]int)
+ // 拷贝一份原始数组
+ rawNums := make([]int,len(nums))
+ copy(rawNums,nums)
+ // 将数组排序
+ sort.Ints(nums)
+ // 循环遍历排序后的数组,值为map的key,索引为value
+ for i,v := range nums {
+ _,contains := m[v]
+ if !contains {
+ m[v] = i
+ }
+
+ }
+ // 返回值结果
+ result := make([]int,len(nums))
+ // 根据原始数组的位置,存放对应的比它小的数
+ for i,v := range rawNums {
+ result[i] = m[v]
+ }
+
+ return result
+}
+```
JavaScript:
```javascript