mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-06 07:06:42 +08:00
Merge branch 'master' of github.com:youngyangyang04/leetcode-master
This commit is contained in:
@ -309,25 +309,25 @@ public:
|
||||
0112.路径总和
|
||||
|
||||
```java
|
||||
class solution {
|
||||
public boolean haspathsum(treenode root, int targetsum) {
|
||||
class Solution {
|
||||
public boolean hasPathSum(TreeNode root, int targetSum) {
|
||||
if (root == null) {
|
||||
return false;
|
||||
}
|
||||
targetsum -= root.val;
|
||||
targetSum -= root.val;
|
||||
// 叶子结点
|
||||
if (root.left == null && root.right == null) {
|
||||
return targetsum == 0;
|
||||
return targetSum == 0;
|
||||
}
|
||||
if (root.left != null) {
|
||||
boolean left = haspathsum(root.left, targetsum);
|
||||
if (left) { // 已经找到
|
||||
boolean left = hasPathSum(root.left, targetSum);
|
||||
if (left) { // 已经找到,提前返回
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (root.right != null) {
|
||||
boolean right = haspathsum(root.right, targetsum);
|
||||
if (right) { // 已经找到
|
||||
boolean right = hasPathSum(root.right, targetSum);
|
||||
if (right) { // 已经找到,提前返回
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -336,16 +336,16 @@ class solution {
|
||||
}
|
||||
|
||||
// lc112 简洁方法
|
||||
class solution {
|
||||
public boolean haspathsum(treenode root, int targetsum) {
|
||||
class Solution {
|
||||
public boolean hasPathSum(TreeNode root, int targetSum) {
|
||||
|
||||
if (root == null) return false; // 为空退出
|
||||
|
||||
// 叶子节点判断是否符合
|
||||
if (root.left == null && root.right == null) return root.val == targetsum;
|
||||
if (root.left == null && root.right == null) return root.val == targetSum;
|
||||
|
||||
// 求两侧分支的路径和
|
||||
return haspathsum(root.left, targetsum - root.val) || haspathsum(root.right, targetsum - root.val);
|
||||
return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -353,22 +353,22 @@ class solution {
|
||||
迭代
|
||||
|
||||
```java
|
||||
class solution {
|
||||
public boolean haspathsum(treenode root, int targetsum) {
|
||||
class Solution {
|
||||
public boolean hasPathSum(TreeNode root, int targetSum) {
|
||||
if(root == null) return false;
|
||||
stack<treenode> stack1 = new stack<>();
|
||||
stack<integer> stack2 = new stack<>();
|
||||
Stack<TreeNode> stack1 = new Stack<>();
|
||||
Stack<Integer> stack2 = new Stack<>();
|
||||
stack1.push(root);
|
||||
stack2.push(root.val);
|
||||
while(!stack1.isempty()) {
|
||||
while(!stack1.isEmpty()) {
|
||||
int size = stack1.size();
|
||||
|
||||
for(int i = 0; i < size; i++) {
|
||||
treenode node = stack1.pop();
|
||||
TreeNode node = stack1.pop();
|
||||
int sum = stack2.pop();
|
||||
|
||||
// 如果该节点是叶子节点了,同时该节点的路径数值等于sum,那么就返回true
|
||||
if(node.left == null && node.right == null && sum == targetsum) {
|
||||
if(node.left == null && node.right == null && sum == targetSum) {
|
||||
return true;
|
||||
}
|
||||
// 右节点,压进去一个节点的时候,将该节点的路径数值也记录下来
|
||||
@ -387,8 +387,9 @@ class solution {
|
||||
}
|
||||
}
|
||||
```
|
||||
```Java 統一迭代法
|
||||
public boolean hasPathSum(TreeNode root, int targetSum) {
|
||||
```Java
|
||||
class Solution {
|
||||
public boolean hasPathSum(TreeNode root, int targetSum) {
|
||||
Stack<TreeNode> treeNodeStack = new Stack<>();
|
||||
Stack<Integer> sumStack = new Stack<>();
|
||||
|
||||
@ -422,38 +423,39 @@ class solution {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
0113.路径总和-ii
|
||||
|
||||
```java
|
||||
class solution {
|
||||
public List<List<Integer>> pathsum(TreeNode root, int targetsum) {
|
||||
class Solution {
|
||||
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
|
||||
List<List<Integer>> res = new ArrayList<>();
|
||||
if (root == null) return res; // 非空判断
|
||||
|
||||
List<Integer> path = new LinkedList<>();
|
||||
preorderdfs(root, targetsum, res, path);
|
||||
preOrderDfs(root, targetSum, res, path);
|
||||
return res;
|
||||
}
|
||||
|
||||
public void preorderdfs(TreeNode root, int targetsum, List<List<Integer>> res, List<Integer> path) {
|
||||
public void preOrderDfs(TreeNode root, int targetSum, List<List<Integer>> res, List<Integer> path) {
|
||||
path.add(root.val);
|
||||
// 遇到了叶子节点
|
||||
if (root.left == null && root.right == null) {
|
||||
// 找到了和为 targetsum 的路径
|
||||
if (targetsum - root.val == 0) {
|
||||
if (targetSum - root.val == 0) {
|
||||
res.add(new ArrayList<>(path));
|
||||
}
|
||||
return; // 如果和不为 targetsum,返回
|
||||
}
|
||||
|
||||
if (root.left != null) {
|
||||
preorderdfs(root.left, targetsum - root.val, res, path);
|
||||
preOrderDfs(root.left, targetSum - root.val, res, path);
|
||||
path.remove(path.size() - 1); // 回溯
|
||||
}
|
||||
if (root.right != null) {
|
||||
preorderdfs(root.right, targetsum - root.val, res, path);
|
||||
preOrderDfs(root.right, targetSum - root.val, res, path);
|
||||
path.remove(path.size() - 1); // 回溯
|
||||
}
|
||||
}
|
||||
@ -1626,3 +1628,4 @@ public class Solution {
|
||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||
</a>
|
||||
|
||||
|
@ -261,8 +261,70 @@ public:
|
||||
|
||||
## 其他语言版本
|
||||
|
||||
|
||||
### Java
|
||||
|
||||
三维DP数组实现
|
||||
|
||||
```java
|
||||
class Solution {
|
||||
public int findMaxForm(String[] strs, int m, int n) {
|
||||
/// 数组有三个维度
|
||||
// 第一个维度:取前面的几个字符串
|
||||
// 第二个维度:0的数量限制(背包维度 1 容量)
|
||||
// 第三个维度:1的数量限制(背包维度 2 容量)
|
||||
int[][][] dpArr = new int[strs.length][m + 1][n + 1];
|
||||
|
||||
/// 初始化dpArr数组
|
||||
// 计算第一个字符串的零数量和1数量
|
||||
int zeroNum = 0;
|
||||
int oneNum = 0;
|
||||
for (char c : strs[0].toCharArray()) {
|
||||
if (c == '0') {
|
||||
zeroNum++;
|
||||
} else {
|
||||
oneNum++;
|
||||
}
|
||||
}
|
||||
// 当0数量、1数量都容得下第一个字符串时,将DP数组的相应位置初始化为1,因为当前的子集数量为1
|
||||
for (int j = zeroNum; j <= m; j++) {
|
||||
for (int k = oneNum; k <= n; k++) {
|
||||
dpArr[0][j][k] = 1;
|
||||
}
|
||||
}
|
||||
/// 依次填充加入第i个字符串之后的DP数组
|
||||
for (int i = 1; i < strs.length; i++) {
|
||||
zeroNum = 0;
|
||||
oneNum = 0;
|
||||
for (char c : strs[i].toCharArray()) {
|
||||
if (c == '0') {
|
||||
zeroNum++;
|
||||
} else {
|
||||
oneNum++;
|
||||
}
|
||||
}
|
||||
for (int j = 0; j <= m; j++) {
|
||||
for (int k = 0; k <= n; k++) {
|
||||
if (j >= zeroNum && k >= oneNum) {
|
||||
// --if-- 当0数量维度和1数量维度的容量都大于等于当前字符串的0数量和1数量时,才考虑是否将当前字符串放入背包
|
||||
// 不放入第i个字符串,子集数量仍为 dpArr[i - 1][j][k]
|
||||
// 放入第i个字符串,需要在0维度腾出 zeroNum 个容量,1维度腾出 oneNum 个容量,然后放入当前字符串,即 dpArr[i - 1][j - zeroNum][k - oneNum] + 1)
|
||||
dpArr[i][j][k] = Math.max(dpArr[i - 1][j][k], dpArr[i - 1][j - zeroNum][k - oneNum] + 1);
|
||||
} else {
|
||||
// --if-- 无法放入第i个字符串,子集数量仍为 dpArr[i - 1][j][k]
|
||||
dpArr[i][j][k] = dpArr[i - 1][j][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return dpArr[dpArr.length - 1][m][n];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
二维DP数组实现
|
||||
|
||||
```Java
|
||||
class Solution {
|
||||
public int findMaxForm(String[] strs, int m, int n) {
|
||||
@ -682,3 +744,4 @@ public class Solution
|
||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||
</a>
|
||||
|
||||
|
@ -825,30 +825,69 @@ func abs(x int) int {
|
||||
|
||||
### JavaScript
|
||||
```javascript
|
||||
/**
|
||||
* 题目来源: {@link https://leetcode.cn/problems/target-sum/}
|
||||
*
|
||||
* 题解来源: {@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}
|
||||
*
|
||||
* 时间复杂度: O(n * C), C 为数组元素总和与目标值之和的一半
|
||||
*
|
||||
* 空间复杂度: O(C)
|
||||
*
|
||||
* @param { number[] } nums
|
||||
* @param { number } target
|
||||
* @return { number }
|
||||
*/
|
||||
const findTargetSumWays = (nums, target) => {
|
||||
// 原题目可转化为:
|
||||
//
|
||||
// 将所有元素划分为 2 个集合,
|
||||
// 一个集合中包含所有要添加 "+" 号的元素, 一个集合中包含所有要添加 "-" 号的元素
|
||||
//
|
||||
// 设两个集合的元素和分别为 positive 和 negative, 所有元素总和为 sum, 那么有如下等式:
|
||||
// positive + negative = sum (1)
|
||||
// positive - negative = target (2)
|
||||
// (1) 与 (2) 联立可得: positive = (sum + target) / 2,
|
||||
// 所以如果能从原数组中取出若干个元素形成 1 个元素总和为 (sum + target) / 2 的集合,
|
||||
// 就算得到了 1 种满足题意的组合方法
|
||||
//
|
||||
// 因此, 所求变为: 有多少种取法, 可使得容量为 (sum + target) / 2 的背包被装满?
|
||||
|
||||
const sum = nums.reduce((a, b) => a+b);
|
||||
const sum = nums.reduce((a, b) => a + b);
|
||||
|
||||
if(Math.abs(target) > sum) {
|
||||
if (Math.abs(target) > sum) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if((target + sum) % 2) {
|
||||
if ((target + sum) % 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const halfSum = (target + sum) / 2;
|
||||
|
||||
let dp = new Array(halfSum+1).fill(0);
|
||||
const bagWeight = (target + sum) / 2;
|
||||
|
||||
// 1. dp 数组的含义
|
||||
// dp[j]: 装满容量为 j 的背包, 有 dp[j] 种方法
|
||||
let dp = new Array(bagWeight + 1).fill(0);
|
||||
|
||||
// 2. 递推公式
|
||||
// dp[j] = Σ(dp[j - nums[j]]), (j ∈ [0, j] 且 j >= nums[j])
|
||||
// 因为 dp[j - nums[j]] 表示: 装满容量为 j - nums[j] 背包有 dp[j - nums[j]] 种方法
|
||||
// 而容量为 j - nums[j] 的背包只需要再将 nums[j] 放入背包就能使得背包容量达到 j
|
||||
// 因此, 让背包容量达到 j 有 Σ(dp[j - nums[j]]) 种方法
|
||||
|
||||
// 3. dp 数组如何初始化
|
||||
// dp[0] = 1, dp[1 ~ bagWeight] = 0
|
||||
dp[0] = 1;
|
||||
|
||||
for(let i = 0; i < nums.length; i++) {
|
||||
for(let j = halfSum; j >= nums[i]; j--) {
|
||||
|
||||
// 4. 遍历顺序
|
||||
// 先物品后背包, 物品从前往后遍历, 背包容量从后往前遍历
|
||||
for (let i = 0; i < nums.length; i++) {
|
||||
for (let j = bagWeight; j >= nums[i]; j--) {
|
||||
dp[j] += dp[j - nums[i]];
|
||||
}
|
||||
}
|
||||
|
||||
return dp[halfSum];
|
||||
return dp[bagWeight];
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -153,23 +153,27 @@ public:
|
||||
递归
|
||||
```java
|
||||
class Solution {
|
||||
TreeNode pre;// 记录上一个遍历的结点
|
||||
TreeNode pre; // 记录上一个遍历的结点
|
||||
int result = Integer.MAX_VALUE;
|
||||
|
||||
public int getMinimumDifference(TreeNode root) {
|
||||
if(root==null)return 0;
|
||||
traversal(root);
|
||||
return result;
|
||||
if (root == null)
|
||||
return 0;
|
||||
traversal(root);
|
||||
return result;
|
||||
}
|
||||
public void traversal(TreeNode root){
|
||||
if(root==null)return;
|
||||
//左
|
||||
|
||||
public void traversal(TreeNode root) {
|
||||
if (root == null)
|
||||
return;
|
||||
// 左
|
||||
traversal(root.left);
|
||||
//中
|
||||
if(pre!=null){
|
||||
result = Math.min(result,root.val-pre.val);
|
||||
// 中
|
||||
if (pre != null) {
|
||||
result = Math.min(result, root.val - pre.val);
|
||||
}
|
||||
pre = root;
|
||||
//右
|
||||
// 右
|
||||
traversal(root.right);
|
||||
}
|
||||
}
|
||||
@ -182,22 +186,27 @@ class Solution {
|
||||
TreeNode pre = null;
|
||||
int result = Integer.MAX_VALUE;
|
||||
|
||||
if(root != null)
|
||||
if (root != null)
|
||||
stack.add(root);
|
||||
while(!stack.isEmpty()){
|
||||
|
||||
// 中序遍历(左中右),由于栈先入后出,反序(右中左)
|
||||
while (!stack.isEmpty()) {
|
||||
TreeNode curr = stack.peek();
|
||||
if(curr != null){
|
||||
if (curr != null) {
|
||||
stack.pop();
|
||||
if(curr.right != null)
|
||||
// 右
|
||||
if (curr.right != null)
|
||||
stack.add(curr.right);
|
||||
// 中(先用null标记)
|
||||
stack.add(curr);
|
||||
stack.add(null);
|
||||
if(curr.left != null)
|
||||
// 左
|
||||
if (curr.left != null)
|
||||
stack.add(curr.left);
|
||||
}else{
|
||||
} else { // 中(遇到null再处理)
|
||||
stack.pop();
|
||||
TreeNode temp = stack.pop();
|
||||
if(pre != null)
|
||||
if (pre != null)
|
||||
result = Math.min(result, temp.val - pre.val);
|
||||
pre = temp;
|
||||
}
|
||||
@ -674,3 +683,4 @@ public class Solution
|
||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||
</a>
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
## 思路
|
||||
|
||||
如果想把这道题目做到极致,就不要只用额外的辅助空间了! (不过使用Java刷题的录友,一定要使用辅助空间,因为Java里的string不能修改)
|
||||
如果想把这道题目做到极致,就不要只用额外的辅助空间了! (不过使用Java和Python刷题的录友,一定要使用辅助空间,因为Java和Python里的string不能修改)
|
||||
|
||||
首先扩充数组到每个数字字符替换成 "number" 之后的大小。
|
||||
|
||||
@ -215,6 +215,46 @@ public class Main {
|
||||
}
|
||||
```
|
||||
|
||||
### Python:
|
||||
```python
|
||||
class Solution(object):
|
||||
def subsitute_numbers(self, s):
|
||||
"""
|
||||
:type s: str
|
||||
:rtype: str
|
||||
"""
|
||||
|
||||
count = sum(1 for char in s if char.isdigit()) # 统计数字的个数
|
||||
expand_len = len(s) + (count * 5) # 计算扩充后字符串的大小, x->number, 每有一个数字就要增加五个长度
|
||||
res = [''] * expand_len
|
||||
|
||||
new_index = expand_len - 1 # 指向扩充后字符串末尾
|
||||
old_index = len(s) - 1 # 指向原字符串末尾
|
||||
|
||||
while old_index >= 0: # 从后往前, 遇到数字替换成“number”
|
||||
if s[old_index].isdigit():
|
||||
res[new_index-5:new_index+1] = "number"
|
||||
new_index -= 6
|
||||
else:
|
||||
res[new_index] = s[old_index]
|
||||
new_index -= 1
|
||||
old_index -= 1
|
||||
|
||||
return "".join(res)
|
||||
|
||||
if __name__ == "__main__":
|
||||
solution = Solution()
|
||||
|
||||
while True:
|
||||
try:
|
||||
s = input()
|
||||
result = solution.subsitute_numbers(s)
|
||||
print(result)
|
||||
except EOFError:
|
||||
break
|
||||
|
||||
```
|
||||
|
||||
### Go:
|
||||
````go
|
||||
package main
|
||||
|
@ -176,6 +176,81 @@ int main() {
|
||||
|
||||
### Java
|
||||
|
||||
```java
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Main {
|
||||
private static int[] father;
|
||||
|
||||
public static void main(String[] args) {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
int pointNum = scanner.nextInt();
|
||||
father = new int[pointNum + 1];
|
||||
init();
|
||||
for (int i = 0; i < pointNum; i++) {
|
||||
join(scanner.nextInt(), scanner.nextInt());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 并查集初始化
|
||||
*/
|
||||
private static void init() {
|
||||
for (int i = 1; i < father.length; i++) {
|
||||
// 让每个元素指向自己
|
||||
father[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 并查集寻根
|
||||
*
|
||||
* @param u
|
||||
* @return
|
||||
*/
|
||||
private static int find(int u) {
|
||||
// 判断 u 是否等于自己,如果是的话,直接返回自己
|
||||
// 如果不等于自己,就寻找根,寻找的时候,反复进行路径压缩
|
||||
return u == father[u] ? u : (father[u] = find(father[u]));
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断 u 和 v 是否同根
|
||||
*
|
||||
* @param u
|
||||
* @param v
|
||||
* @return
|
||||
*/
|
||||
private static boolean isSame(int u, int v) {
|
||||
return find(u) == find(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加 边 到并查集,v 指向 u
|
||||
*
|
||||
* @param u
|
||||
* @param v
|
||||
*/
|
||||
private static void join(int u, int v) {
|
||||
// --if-- 如果两个点已经同根,说明他们的信息已经存储到并查集中了,直接返回即可
|
||||
// 寻找u的根
|
||||
int uRoot = find(u);
|
||||
// 寻找v的根
|
||||
int vRoot = find(v);
|
||||
if (uRoot == vRoot) {
|
||||
// --if-- 如果u,v的根相同,说明两者已经连接了,直接输出
|
||||
System.out.println(u + " " + v);
|
||||
return;
|
||||
}
|
||||
// --if-- 将信息添加到并查集
|
||||
father[vRoot] = uRoot;
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Python
|
||||
|
||||
```python
|
||||
|
@ -92,10 +92,9 @@
|
||||
* 递归:中序,双指针操作
|
||||
* 迭代:模拟中序,逻辑相同
|
||||
* [求二叉搜索树的众数](https://programmercarl.com/0501.二叉搜索树中的众数.html)
|
||||
|
||||
|
||||
* 递归:中序,清空结果集的技巧,遍历一遍便可求众数集合
|
||||
* [二叉搜索树转成累加树](https://programmercarl.com/0538.把二叉搜索树转换为累加树.html)
|
||||
|
||||
* [二叉搜索树转成累加树](https://programmercarl.com/0538.把二叉搜索树转换为累加树.html)
|
||||
* 递归:中序,双指针操作累加
|
||||
* 迭代:模拟中序,逻辑相同
|
||||
|
||||
@ -163,3 +162,4 @@
|
||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||
</a>
|
||||
|
||||
|
Reference in New Issue
Block a user