Skip to content

Commit 7a138de

Browse files
Merge branch 'master' of github.com:youngyangyang04/leetcode-master
2 parents 82c7f09 + e5b75df commit 7a138de

7 files changed

+292
-62
lines changed

problems/0112.路径总和.md

+31-28
Original file line numberDiff line numberDiff line change
@@ -309,25 +309,25 @@ public:
309309
0112.路径总和
310310

311311
```java
312-
class solution {
313-
public boolean haspathsum(treenode root, int targetsum) {
312+
class Solution {
313+
public boolean hasPathSum(TreeNode root, int targetSum) {
314314
if (root == null) {
315315
return false;
316316
}
317-
targetsum -= root.val;
317+
targetSum -= root.val;
318318
// 叶子结点
319319
if (root.left == null && root.right == null) {
320-
return targetsum == 0;
320+
return targetSum == 0;
321321
}
322322
if (root.left != null) {
323-
boolean left = haspathsum(root.left, targetsum);
324-
if (left) { // 已经找到
323+
boolean left = hasPathSum(root.left, targetSum);
324+
if (left) { // 已经找到,提前返回
325325
return true;
326326
}
327327
}
328328
if (root.right != null) {
329-
boolean right = haspathsum(root.right, targetsum);
330-
if (right) { // 已经找到
329+
boolean right = hasPathSum(root.right, targetSum);
330+
if (right) { // 已经找到,提前返回
331331
return true;
332332
}
333333
}
@@ -336,39 +336,39 @@ class solution {
336336
}
337337

338338
// lc112 简洁方法
339-
class solution {
340-
public boolean haspathsum(treenode root, int targetsum) {
339+
class Solution {
340+
public boolean hasPathSum(TreeNode root, int targetSum) {
341341

342342
if (root == null) return false; // 为空退出
343343

344344
// 叶子节点判断是否符合
345-
if (root.left == null && root.right == null) return root.val == targetsum;
345+
if (root.left == null && root.right == null) return root.val == targetSum;
346346

347347
// 求两侧分支的路径和
348-
return haspathsum(root.left, targetsum - root.val) || haspathsum(root.right, targetsum - root.val);
348+
return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
349349
}
350350
}
351351
```
352352

353353
迭代
354354

355355
```java
356-
class solution {
357-
public boolean haspathsum(treenode root, int targetsum) {
356+
class Solution {
357+
public boolean hasPathSum(TreeNode root, int targetSum) {
358358
if(root == null) return false;
359-
stack<treenode> stack1 = new stack<>();
360-
stack<integer> stack2 = new stack<>();
359+
Stack<TreeNode> stack1 = new Stack<>();
360+
Stack<Integer> stack2 = new Stack<>();
361361
stack1.push(root);
362362
stack2.push(root.val);
363-
while(!stack1.isempty()) {
363+
while(!stack1.isEmpty()) {
364364
int size = stack1.size();
365365

366366
for(int i = 0; i < size; i++) {
367-
treenode node = stack1.pop();
367+
TreeNode node = stack1.pop();
368368
int sum = stack2.pop();
369369

370370
// 如果该节点是叶子节点了,同时该节点的路径数值等于sum,那么就返回true
371-
if(node.left == null && node.right == null && sum == targetsum) {
371+
if(node.left == null && node.right == null && sum == targetSum) {
372372
return true;
373373
}
374374
// 右节点,压进去一个节点的时候,将该节点的路径数值也记录下来
@@ -387,8 +387,9 @@ class solution {
387387
}
388388
}
389389
```
390-
```Java 統一迭代法
391-
public boolean hasPathSum(TreeNode root, int targetSum) {
390+
```Java
391+
class Solution {
392+
public boolean hasPathSum(TreeNode root, int targetSum) {
392393
Stack<TreeNode> treeNodeStack = new Stack<>();
393394
Stack<Integer> sumStack = new Stack<>();
394395

@@ -422,38 +423,39 @@ class solution {
422423
}
423424
return false;
424425
}
426+
}
425427
```
426428

427429
0113.路径总和-ii
428430

429431
```java
430-
class solution {
431-
public List<List<Integer>> pathsum(TreeNode root, int targetsum) {
432+
class Solution {
433+
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
432434
List<List<Integer>> res = new ArrayList<>();
433435
if (root == null) return res; // 非空判断
434436

435437
List<Integer> path = new LinkedList<>();
436-
preorderdfs(root, targetsum, res, path);
438+
preOrderDfs(root, targetSum, res, path);
437439
return res;
438440
}
439441

440-
public void preorderdfs(TreeNode root, int targetsum, List<List<Integer>> res, List<Integer> path) {
442+
public void preOrderDfs(TreeNode root, int targetSum, List<List<Integer>> res, List<Integer> path) {
441443
path.add(root.val);
442444
// 遇到了叶子节点
443445
if (root.left == null && root.right == null) {
444446
// 找到了和为 targetsum 的路径
445-
if (targetsum - root.val == 0) {
447+
if (targetSum - root.val == 0) {
446448
res.add(new ArrayList<>(path));
447449
}
448450
return; // 如果和不为 targetsum,返回
449451
}
450452

451453
if (root.left != null) {
452-
preorderdfs(root.left, targetsum - root.val, res, path);
454+
preOrderDfs(root.left, targetSum - root.val, res, path);
453455
path.remove(path.size() - 1); // 回溯
454456
}
455457
if (root.right != null) {
456-
preorderdfs(root.right, targetsum - root.val, res, path);
458+
preOrderDfs(root.right, targetSum - root.val, res, path);
457459
path.remove(path.size() - 1); // 回溯
458460
}
459461
}
@@ -1626,3 +1628,4 @@ public class Solution {
16261628
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
16271629
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
16281630
</a>
1631+

problems/0474.一和零.md

+64-1
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,70 @@ public:
261261

262262
## 其他语言版本
263263

264-
265264
### Java
265+
266+
三维DP数组实现
267+
268+
```java
269+
class Solution {
270+
public int findMaxForm(String[] strs, int m, int n) {
271+
/// 数组有三个维度
272+
// 第一个维度:取前面的几个字符串
273+
// 第二个维度:0的数量限制(背包维度 1 容量)
274+
// 第三个维度:1的数量限制(背包维度 2 容量)
275+
int[][][] dpArr = new int[strs.length][m + 1][n + 1];
276+
277+
/// 初始化dpArr数组
278+
// 计算第一个字符串的零数量和1数量
279+
int zeroNum = 0;
280+
int oneNum = 0;
281+
for (char c : strs[0].toCharArray()) {
282+
if (c == '0') {
283+
zeroNum++;
284+
} else {
285+
oneNum++;
286+
}
287+
}
288+
// 当0数量、1数量都容得下第一个字符串时,将DP数组的相应位置初始化为1,因为当前的子集数量为1
289+
for (int j = zeroNum; j <= m; j++) {
290+
for (int k = oneNum; k <= n; k++) {
291+
dpArr[0][j][k] = 1;
292+
}
293+
}
294+
/// 依次填充加入第i个字符串之后的DP数组
295+
for (int i = 1; i < strs.length; i++) {
296+
zeroNum = 0;
297+
oneNum = 0;
298+
for (char c : strs[i].toCharArray()) {
299+
if (c == '0') {
300+
zeroNum++;
301+
} else {
302+
oneNum++;
303+
}
304+
}
305+
for (int j = 0; j <= m; j++) {
306+
for (int k = 0; k <= n; k++) {
307+
if (j >= zeroNum && k >= oneNum) {
308+
// --if-- 当0数量维度和1数量维度的容量都大于等于当前字符串的0数量和1数量时,才考虑是否将当前字符串放入背包
309+
// 不放入第i个字符串,子集数量仍为 dpArr[i - 1][j][k]
310+
// 放入第i个字符串,需要在0维度腾出 zeroNum 个容量,1维度腾出 oneNum 个容量,然后放入当前字符串,即 dpArr[i - 1][j - zeroNum][k - oneNum] + 1)
311+
dpArr[i][j][k] = Math.max(dpArr[i - 1][j][k], dpArr[i - 1][j - zeroNum][k - oneNum] + 1);
312+
} else {
313+
// --if-- 无法放入第i个字符串,子集数量仍为 dpArr[i - 1][j][k]
314+
dpArr[i][j][k] = dpArr[i - 1][j][k];
315+
}
316+
}
317+
}
318+
}
319+
return dpArr[dpArr.length - 1][m][n];
320+
}
321+
}
322+
```
323+
324+
325+
326+
二维DP数组实现
327+
266328
```Java
267329
class Solution {
268330
public int findMaxForm(String[] strs, int m, int n) {
@@ -682,3 +744,4 @@ public class Solution
682744
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
683745
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
684746
</a>
747+

problems/0494.目标和.md

+50-11
Original file line numberDiff line numberDiff line change
@@ -825,30 +825,69 @@ func abs(x int) int {
825825

826826
### JavaScript
827827
```javascript
828+
/**
829+
* 题目来源: {@link https://leetcode.cn/problems/target-sum/}
830+
*
831+
* 题解来源: {@link https://programmercarl.com/0494.%E7%9B%AE%E6%A0%87%E5%92%8C.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE}
832+
*
833+
* 时间复杂度: O(n * C), C 为数组元素总和与目标值之和的一半
834+
*
835+
* 空间复杂度: O(C)
836+
*
837+
* @param { number[] } nums
838+
* @param { number } target
839+
* @return { number }
840+
*/
828841
const findTargetSumWays = (nums, target) => {
829-
830-
const sum = nums.reduce((a, b) => a+b);
842+
// 原题目可转化为:
843+
//
844+
// 将所有元素划分为 2 个集合,
845+
// 一个集合中包含所有要添加 "+" 号的元素, 一个集合中包含所有要添加 "-" 号的元素
846+
//
847+
// 设两个集合的元素和分别为 positive 和 negative, 所有元素总和为 sum, 那么有如下等式:
848+
// positive + negative = sum (1)
849+
// positive - negative = target (2)
850+
// (1) 与 (2) 联立可得: positive = (sum + target) / 2,
851+
// 所以如果能从原数组中取出若干个元素形成 1 个元素总和为 (sum + target) / 2 的集合,
852+
// 就算得到了 1 种满足题意的组合方法
853+
//
854+
// 因此, 所求变为: 有多少种取法, 可使得容量为 (sum + target) / 2 的背包被装满?
855+
856+
const sum = nums.reduce((a, b) => a + b);
831857

832-
if(Math.abs(target) > sum) {
858+
if (Math.abs(target) > sum) {
833859
return 0;
834860
}
835861

836-
if((target + sum) % 2) {
862+
if ((target + sum) % 2) {
837863
return 0;
838864
}
839865

840-
const halfSum = (target + sum) / 2;
841-
842-
let dp = new Array(halfSum+1).fill(0);
866+
const bagWeight = (target + sum) / 2;
867+
868+
// 1. dp 数组的含义
869+
// dp[j]: 装满容量为 j 的背包, 有 dp[j] 种方法
870+
let dp = new Array(bagWeight + 1).fill(0);
871+
872+
// 2. 递推公式
873+
// dp[j] = Σ(dp[j - nums[j]]), (j ∈ [0, j] 且 j >= nums[j])
874+
// 因为 dp[j - nums[j]] 表示: 装满容量为 j - nums[j] 背包有 dp[j - nums[j]] 种方法
875+
// 而容量为 j - nums[j] 的背包只需要再将 nums[j] 放入背包就能使得背包容量达到 j
876+
// 因此, 让背包容量达到 j 有 Σ(dp[j - nums[j]]) 种方法
877+
878+
// 3. dp 数组如何初始化
879+
// dp[0] = 1, dp[1 ~ bagWeight] = 0
843880
dp[0] = 1;
844-
845-
for(let i = 0; i < nums.length; i++) {
846-
for(let j = halfSum; j >= nums[i]; j--) {
881+
882+
// 4. 遍历顺序
883+
// 先物品后背包, 物品从前往后遍历, 背包容量从后往前遍历
884+
for (let i = 0; i < nums.length; i++) {
885+
for (let j = bagWeight; j >= nums[i]; j--) {
847886
dp[j] += dp[j - nums[i]];
848887
}
849888
}
850889

851-
return dp[halfSum];
890+
return dp[bagWeight];
852891
};
853892
```
854893

problems/0530.二叉搜索树的最小绝对差.md

+28-18
Original file line numberDiff line numberDiff line change
@@ -153,23 +153,27 @@ public:
153153
递归
154154
```java
155155
class Solution {
156-
TreeNode pre;// 记录上一个遍历的结点
156+
TreeNode pre; // 记录上一个遍历的结点
157157
int result = Integer.MAX_VALUE;
158+
158159
public int getMinimumDifference(TreeNode root) {
159-
if(root==null)return 0;
160-
traversal(root);
161-
return result;
160+
if (root == null)
161+
return 0;
162+
traversal(root);
163+
return result;
162164
}
163-
public void traversal(TreeNode root){
164-
if(root==null)return;
165-
//左
165+
166+
public void traversal(TreeNode root) {
167+
if (root == null)
168+
return;
169+
// 左
166170
traversal(root.left);
167-
//中
168-
if(pre!=null){
169-
result = Math.min(result,root.val-pre.val);
171+
//
172+
if (pre != null) {
173+
result = Math.min(result, root.val - pre.val);
170174
}
171175
pre = root;
172-
//右
176+
//
173177
traversal(root.right);
174178
}
175179
}
@@ -182,22 +186,27 @@ class Solution {
182186
TreeNode pre = null;
183187
int result = Integer.MAX_VALUE;
184188

185-
if(root != null)
189+
if (root != null)
186190
stack.add(root);
187-
while(!stack.isEmpty()){
191+
192+
// 中序遍历(左中右),由于栈先入后出,反序(右中左)
193+
while (!stack.isEmpty()) {
188194
TreeNode curr = stack.peek();
189-
if(curr != null){
195+
if (curr != null) {
190196
stack.pop();
191-
if(curr.right != null)
197+
//
198+
if (curr.right != null)
192199
stack.add(curr.right);
200+
// 中(先用null标记)
193201
stack.add(curr);
194202
stack.add(null);
195-
if(curr.left != null)
203+
//
204+
if (curr.left != null)
196205
stack.add(curr.left);
197-
}else{
206+
} else { // 中(遇到null再处理)
198207
stack.pop();
199208
TreeNode temp = stack.pop();
200-
if(pre != null)
209+
if (pre != null)
201210
result = Math.min(result, temp.val - pre.val);
202211
pre = temp;
203212
}
@@ -674,3 +683,4 @@ public class Solution
674683
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
675684
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
676685
</a>
686+

0 commit comments

Comments
 (0)