Skip to content

Commit b7bc162

Browse files
Merge branch 'master' of github.com:youngyangyang04/leetcode-master
2 parents 78bfec7 + 62b0c68 commit b7bc162

7 files changed

+258
-80
lines changed

problems/0110.平衡二叉树.md

+14-20
Original file line numberDiff line numberDiff line change
@@ -607,29 +607,23 @@ func abs(a int)int{
607607
## JavaScript
608608
```javascript
609609
var isBalanced = function(root) {
610-
//还是用递归三部曲 + 后序遍历 左右中 当前左子树右子树高度相差大于1就返回-1
610+
//还是用递归三部曲 + 后序遍历 左右中 当前左子树右子树高度相差大于1就返回-1
611611
// 1. 确定递归函数参数以及返回值
612-
const getDepth=function(node){
613-
// 2. 确定递归函数终止条件
614-
if(node===null){
615-
return 0;
612+
const getDepth = function(node) {
613+
// 2. 确定递归函数终止条件
614+
if(node === null) return 0;
615+
// 3. 确定单层递归逻辑
616+
let leftDepth = getDepth(node.left); //左子树高度
617+
let rightDepth = getDepth(node.right); //右子树高度
618+
if(leftDepth === -1) return -1;
619+
if(rightDepth === -1) return -1;
620+
if(Math.abs(leftDepth - rightDepth) > 1) {
621+
return -1;
622+
} else {
623+
return 1 + Math.max(leftDepth, rightDepth);
616624
}
617-
// 3. 确定单层递归逻辑
618-
let leftDepth=getDepth(node.left);//左子树高度
619-
if(leftDepth===-1){
620-
return -1;
621-
}
622-
let rightDepth=getDepth(node.right);//右子树高度
623-
if(rightDepth===-1){
624-
return -1;
625-
}
626-
if(Math.abs(leftDepth-rightDepth)>1){
627-
return -1;
628-
}else{
629-
return 1+Math.max(leftDepth,rightDepth);
630-
}
631625
}
632-
return getDepth(root)===-1?false:true;
626+
return !(getDepth(root) === -1);
633627
};
634628
```
635629

problems/0112.路径总和.md

+66-1
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,7 @@ func haspathsum(root *treenode,sumnodes *[]int,targetsum int,result *[][]int){
614614

615615
0112.路径总和
616616

617+
**递归**
617618
```javascript
618619
/**
619620
* @param {treenode} root
@@ -643,9 +644,38 @@ let haspathsum = function (root, targetsum) {
643644
// return haspathsum(root.left, targetsum - root.val) || haspathsum(root.right, targetsum - root.val);
644645
};
645646
```
647+
**迭代**
648+
```javascript
649+
let hasPathSum = function(root, targetSum) {
650+
if(root === null) return false;
651+
let nodeArr = [root];
652+
let valArr = [0];
653+
while(nodeArr.length) {
654+
let curNode = nodeArr.shift();
655+
let curVal = valArr.shift();
656+
curVal += curNode.val;
657+
// 为叶子结点,且和等于目标数,返回true
658+
if (curNode.left === null && curNode.right === null && curVal === targetSum) {
659+
return true;
660+
}
661+
// 左节点,将当前的数值也对应记录下来
662+
if (curNode.left) {
663+
nodeArr.push(curNode.left);
664+
valArr.push(curVal);
665+
}
666+
// 右节点,将当前的数值也对应记录下来
667+
if (curNode.right) {
668+
nodeArr.push(curNode.right);
669+
valArr.push(curVal);
670+
}
671+
}
672+
return false;
673+
};
674+
```
646675

647676
0113.路径总和-ii
648677

678+
**递归**
649679
```javascript
650680
let pathsum = function (root, targetsum) {
651681
// 递归法
@@ -677,7 +707,7 @@ let pathsum = function (root, targetsum) {
677707
return res;
678708
};
679709
```
680-
113 路径总和 精简版
710+
**递归 精简版**
681711
```javascript
682712
var pathsum = function(root, targetsum) {
683713
//递归方法
@@ -701,6 +731,41 @@ var pathsum = function(root, targetsum) {
701731
return resPath;
702732
};
703733
```
734+
**迭代**
735+
```javascript
736+
let pathSum = function(root, targetSum) {
737+
if(root === null) return [];
738+
let nodeArr = [root];
739+
let resArr = []; // 记录符合目标和的返回路径
740+
let tempArr = [[]]; // 对应路径
741+
let countArr = [0]; //对应和
742+
while(nodeArr.length) {
743+
let curNode = nodeArr.shift();
744+
let curVal = countArr.shift();
745+
let curNodeArr = tempArr.shift();
746+
curVal += curNode.val;
747+
curNodeArr.push(curNode.val);
748+
// 为叶子结点,且和等于目标数,将此次结果数组push进返回数组中
749+
if (curNode.left === null && curNode.right === null && curVal === targetSum) {
750+
resArr.push(curNodeArr);
751+
}
752+
// 左节点,将当前的和及对应路径也对应记录下来
753+
if (curNode.left) {
754+
nodeArr.push(curNode.left);
755+
countArr.push(curVal);
756+
tempArr.push([...curNodeArr]);
757+
}
758+
// 右节点,将当前的和及对应路径也对应记录下来
759+
if (curNode.right) {
760+
nodeArr.push(curNode.right);
761+
countArr.push(curVal);
762+
tempArr.push([...curNodeArr]);
763+
}
764+
}
765+
return resArr;
766+
};
767+
```
768+
704769

705770

706771

problems/0121.买卖股票的最佳时机.md

+35-32
Original file line numberDiff line numberDiff line change
@@ -195,23 +195,26 @@ public:
195195
## 其他语言版本
196196

197197
Java:
198+
199+
> 贪心法:
200+
198201
```java
199-
// 贪心思路
200202
class Solution {
201203
public int maxProfit(int[] prices) {
202-
int minprice = Integer.MAX_VALUE;
203-
int maxprofit = 0;
204-
for (int i = 0; i < prices.length; i++) {
205-
if (prices[i] < minprice) {
206-
minprice = prices[i];
207-
} else if (prices[i] - minprice > maxprofit) {
208-
maxprofit = prices[i] - minprice;
209-
}
204+
// 找到一个最小的购入点
205+
int low = Integer.MAX_VALUE;
206+
// res不断更新,直到数组循环完毕
207+
int res = 0;
208+
for(int i = 0; i < prices.length; i++){
209+
low = Math.min(prices[i], low);
210+
res = Math.max(prices[i] - low, res);
210211
}
211-
return maxprofit;
212+
return res;
212213
}
213214
}
214215
```
216+
> 动态规划:版本一
217+
215218
```java
216219
// 解法1
217220
class Solution {
@@ -233,30 +236,30 @@ class Solution {
233236
}
234237
```
235238

236-
``` java
237-
class Solution { // 动态规划解法
238-
public int maxProfit(int[] prices) {
239-
// 可交易次数
240-
int k = 1;
241-
// [天数][交易次数][是否持有股票]
242-
int[][][] dp = new int[prices.length][k + 1][2];
243-
244-
// bad case
245-
dp[0][0][0] = 0;
246-
dp[0][0][1] = Integer.MIN_VALUE;
247-
dp[0][1][0] = Integer.MIN_VALUE;
248-
dp[0][1][1] = -prices[0];
249-
250-
for (int i = 1; i < prices.length; i++) {
251-
for (int j = k; j >= 1; j--) {
252-
// dp公式
253-
dp[i][j][0] = Math.max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i]);
254-
dp[i][j][1] = Math.max(dp[i - 1][j][1], dp[i - 1][j - 1][0] - prices[i]);
255-
}
256-
}
239+
> 动态规划:版本二
257240

258-
return dp[prices.length - 1][k][0] > 0 ? dp[prices.length - 1][k][0] : 0;
241+
``` java
242+
class Solution {
243+
public int maxProfit(int[] prices) {
244+
int[] dp = new int[2];
245+
dp[0] = -prices[0];
246+
dp[1] = 0;
247+
// 可以参考斐波那契问题的优化方式
248+
// dp[0] 和 dp[1], 其实是第 0 天的数据
249+
// 所以我们从 i=1 开始遍历数组,一共有 prices.length 天,
250+
// 所以是 i<=prices.length
251+
for (int i = 1; i <= prices.length; i++) {
252+
// 前一天持有;或当天买入
253+
dp[0] = Math.max(dp[0], -prices[i - 1]);
254+
// 如果 dp[0] 被更新,那么 dp[1] 肯定会被更新为正数的 dp[1]
255+
// 而不是 dp[0]+prices[i-1]==0 的0,
256+
// 所以这里使用会改变的dp[0]也是可以的
257+
// 当然 dp[1] 初始值为 0 ,被更新成 0 也没影响
258+
// 前一天卖出;或当天卖出, 当天要卖出,得前一天持有才行
259+
dp[1] = Math.max(dp[1], dp[0] + prices[i - 1]);
259260
}
261+
return dp[1];
262+
}
260263
}
261264
```
262265

problems/0122.买卖股票的最佳时机II.md

+19
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,25 @@ class Solution { // 动态规划
167167
}
168168
```
169169

170+
```java
171+
// 优化空间
172+
class Solution {
173+
public int maxProfit(int[] prices) {
174+
int[] dp=new int[2];
175+
// 0表示持有,1表示卖出
176+
dp[0]=-prices[0];
177+
dp[1]=0;
178+
for(int i=1; i<=prices.length; i++){
179+
// 前一天持有; 或当天卖出然后买入
180+
dp[0]=Math.max(dp[0], dp[1]-prices[i-1]);
181+
// 前一天卖出; 或当天卖出,当天卖出,得先持有
182+
dp[1]=Math.max(dp[1], dp[0]+prices[i-1]);
183+
}
184+
return dp[1];
185+
}
186+
}
187+
```
188+
170189

171190

172191
### Python

problems/0123.买卖股票的最佳时机III.md

+24-17
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ dp[1] = max(dp[1], dp[0] - prices[i]); 如果dp[1]取dp[1],即保持买入股
188188

189189
## 其他语言版本
190190

191-
Java
191+
### Java
192192

193193
```java
194194
// 版本一
@@ -221,25 +221,30 @@ class Solution {
221221
// 版本二: 空间优化
222222
class Solution {
223223
public int maxProfit(int[] prices) {
224-
int len = prices.length;
225-
int[] dp = new int[5];
226-
dp[1] = -prices[0];
227-
dp[3] = -prices[0];
228-
229-
for (int i = 1; i < len; i++) {
230-
dp[1] = Math.max(dp[1], dp[0] - prices[i]);
231-
dp[2] = Math.max(dp[2], dp[1] + prices[i]);
232-
dp[3] = Math.max(dp[3], dp[2] - prices[i]);
233-
dp[4] = Math.max(dp[4], dp[3] + prices[i]);
224+
int[] dp=new int[4];
225+
// 存储两天的状态就行了
226+
// dp[0]代表第一次买入
227+
dp[0]=-prices[0];
228+
// dp[1]代表第一次卖出
229+
dp[1]=0;
230+
// dp[2]代表第二次买入
231+
dp[2]=-prices[0];
232+
// dp[3]代表第二次卖出
233+
dp[3]=0;
234+
for(int i=1; i<=prices.length; i++){
235+
// 要么保持不变,要么没有就买,有了就卖
236+
dp[0]=Math.max(dp[0], -prices[i-1]);
237+
dp[1]=Math.max(dp[1], dp[0]+prices[i-1]);
238+
// 这已经是第二天了,所以得加上前一天卖出去的价格
239+
dp[2]=Math.max(dp[2], dp[1]-prices[i-1]);
240+
dp[3]=Math.max(dp[3], dp[2]+prices[i-1]);
234241
}
235-
236-
return dp[4];
242+
return dp[3];
237243
}
238244
}
239245
```
240246

241-
242-
Python:
247+
### Python
243248

244249
> 版本一:
245250
```python
@@ -308,7 +313,7 @@ func max(a,b int)int{
308313

309314

310315

311-
JavaScript
316+
### JavaScript
312317

313318
> 版本一:
314319

@@ -347,7 +352,7 @@ const maxProfit = prices => {
347352
};
348353
```
349354

350-
Go:
355+
### Go
351356

352357
> 版本一:
353358
```go
@@ -381,5 +386,7 @@ func max(a, b int) int {
381386
```
382387

383388

389+
390+
384391
-----------------------
385392
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

problems/0188.买卖股票的最佳时机IV.md

+23-10
Original file line numberDiff line numberDiff line change
@@ -222,19 +222,32 @@ class Solution {
222222
//版本三:一维 dp数组
223223
class Solution {
224224
public int maxProfit(int k, int[] prices) {
225-
//在版本二的基础上,由于我们只关心前一天的股票买入情况,所以只存储前一天的股票买入情况
226-
if(prices.length==0)return 0;
227-
int[] dp=new int[2*k+1];
228-
for (int i = 1; i <2*k ; i+=2) {
229-
dp[i]=-prices[0];
225+
if(prices.length == 0){
226+
return 0;
230227
}
231-
for (int i = 0; i <prices.length ; i++) {
232-
for (int j = 1; j <2*k ; j+=2) {
233-
dp[j]=Math.max(dp[j],dp[j-1]-prices[i]);
234-
dp[j+1]=Math.max(dp[j+1],dp[j]+prices[i]);
228+
if(k == 0){
229+
return 0;
230+
}
231+
// 其实就是123题的扩展,123题只用记录2天的状态
232+
// 这里记录k天的状态就行了
233+
// 每天都有买入,卖出两个状态,所以要乘 2
234+
int[] dp = new int[2 * k];
235+
// 按123题解题格式那样,做一个初始化
236+
for(int i = 0; i < dp.length / 2; i++){
237+
dp[i * 2] = -prices[0];
238+
}
239+
for(int i = 1; i <= prices.length; i++){
240+
dp[0] = Math.max(dp[0], -prices[i - 1]);
241+
dp[1] = Math.max(dp[1], dp[0] + prices[i - 1]);
242+
// 还是与123题一样,与123题对照来看
243+
// 就很容易啦
244+
for(int j = 2; j < dp.length; j += 2){
245+
dp[j] = Math.max(dp[j], dp[j - 1] - prices[i-1]);
246+
dp[j + 1] = Math.max(dp[j + 1], dp[j] + prices[i - 1]);
235247
}
236248
}
237-
return dp[2*k];
249+
// 返回最后一天卖出状态的结果就行了
250+
return dp[dp.length - 1];
238251
}
239252
}
240253
```

0 commit comments

Comments
 (0)