Skip to content

Commit 485f499

Browse files
init
0 parents  commit 485f499

15 files changed

+1370
-0
lines changed

.github/workflows/action.yml

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: 'GitHub LeetCode Bot'
2+
3+
on:
4+
# 执行git push操作将会触发此脚本
5+
push:
6+
7+
# 每隔12小时将会触发此脚本
8+
schedule:
9+
- cron: '0 */12 * * *'
10+
workflow_dispatch:
11+
12+
jobs:
13+
bot:
14+
# 运行环境,Ubuntu
15+
runs-on: ubuntu-latest
16+
steps:
17+
# 检测代码
18+
- name: 'Checkout codes'
19+
uses: actions/checkout@v2
20+
21+
# 修改系统时区
22+
- name: Setup the time zone to Asia/Shanghai
23+
uses: zcong1993/setup-timezone@master
24+
with:
25+
timezone: Asia/Shanghai
26+
27+
# 安装Python3.6
28+
- name: Set up Python
29+
uses: actions/setup-python@v1
30+
with:
31+
python-version: 3.6
32+
33+
# 清除pip缓存
34+
- name: Configure pip cache
35+
uses: actions/cache@v1
36+
id: pip-cache
37+
with:
38+
path: venv
39+
key: pip-1-${{ hashFiles('**/requirements.txt') }}
40+
restore-keys: |
41+
pip-
42+
43+
# 安装requirements.txt中的依赖包
44+
- name: Install dependencies
45+
run: |
46+
python -m pip install --upgrade pip
47+
pip install -r requirements.txt
48+
if: steps.pip-cache.outputs.cache-hit != 'true'
49+
50+
# 运行leetcode.py文件
51+
# 将在程序当前生成目录下生成一个新的README.md文件
52+
- name: Get LeetCode Data
53+
run: python leetcode.py ${{ secrets.LEETCODE_EMAIL }} ${{ secrets.LEETCODE_PASSWORD }}
54+
55+
# 执行push操作,推送最新的README.md文件
56+
- uses: stefanzweifel/git-auto-commit-action@v4
57+
with:
58+
commit_message: Update changes

.gitignore

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# mac OSX
2+
3+
# 忽略所有以.DS_Store结尾的文件
4+
*.DS_Store
5+
6+
# 忽略venv文件夹下的所有文件
7+
/venv/
8+
9+
# 忽略.idea文件夹下的所有文件
10+
/.idea/
11+
12+
# 只忽略__pycache__目录,不忽略__pycache__文件
13+
__pycache__/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#### 1926. 迷宫中离入口最近的出口
2+
3+
难度:中等
4+
5+
---
6+
7+
给你一个 `m x n` 的迷宫矩阵 `maze`**下标从 0 开始** ),矩阵中有空格子(用 `'.'` 表示)和墙(用 `'+'` 表示)。同时给你迷宫的入口 `entrance` ,用 `entrance = [entrancerow, entrancecol]` 表示你一开始所在格子的行和列。
8+
9+
每一步操作,你可以往 ************ 或者 **** 移动一个格子。你不能进入墙所在的格子,你也不能离开迷宫。你的目标是找到离 `entrance` **最近** 的出口。 **出口** 的含义是 `maze` **边界** 上的 **空格子**`entrance` 格子 **不算** 出口。
10+
11+
请你返回从 `entrance` 到最近出口的最短路径的 **步数** ,如果不存在这样的路径,请你返回 `-1`
12+
13+
**示例 1:**
14+
15+
![](https://assets.leetcode.com/uploads/2021/06/04/nearest1-grid.jpg)
16+
```
17+
输入:maze = [["+","+",".","+"],[".",".",".","+"],["+","+","+","."]], entrance = [1,2]
18+
输出:1
19+
解释:总共有 3 个出口,分别位于 (1,0),(0,2) 和 (2,3) 。
20+
一开始,你在入口格子 (1,2) 处。
21+
- 你可以往左移动 2 步到达 (1,0) 。
22+
- 你可以往上移动 1 步到达 (0,2) 。
23+
从入口处没法到达 (2,3) 。
24+
所以,最近的出口是 (0,2) ,距离为 1 步。
25+
```
26+
27+
**示例 2:**
28+
29+
![](https://assets.leetcode.com/uploads/2021/06/04/nearesr2-grid.jpg)
30+
```
31+
输入:maze = [["+","+","+"],[".",".","."],["+","+","+"]], entrance = [1,0]
32+
输出:2
33+
解释:迷宫中只有 1 个出口,在 (1,2) 处。
34+
(1,0) 不算出口,因为它是入口格子。
35+
初始时,你在入口与格子 (1,0) 处。
36+
- 你可以往右移动 2 步到达 (1,2) 处。
37+
所以,最近的出口为 (1,2) ,距离为 2 步。
38+
```
39+
40+
**示例 3:**
41+
42+
![](https://assets.leetcode.com/uploads/2021/06/04/nearest3-grid.jpg)
43+
```
44+
输入:maze = [[".","+"]], entrance = [0,0]
45+
输出:-1
46+
解释:这个迷宫中没有出口。
47+
```
48+
49+
**提示:**
50+
51+
* `maze.length == m`
52+
* `maze[i].length == n`
53+
* `1 <= m, n <= 100`
54+
* `maze[i][j]` 要么是 `'.'` ,要么是 `'+'`
55+
* `entrance.length == 2`
56+
* `0 <= entrancerow < m`
57+
* `0 <= entrancecol < n`
58+
* `entrance` 一定是空格子。
59+
60+
---
61+
62+
非递归的广度优先搜索,有以下几个技巧:
63+
64+
1. 遍历后将当前点变为****,便不会进行二次操作。
65+
66+
2. 使用**辅助数组**保存四个方位的横坐标及纵坐标的**变化**
67+
68+
```java
69+
class Solution {
70+
public int nearestExit(char[][] maze, int[] entrance) {
71+
int[][] dir = new int[][]{{1, 0},{-1, 0},{0, 1},{0, -1}};
72+
int ans = 0;
73+
ArrayDeque<int[]> queue = new ArrayDeque<>();
74+
queue.offer(entrance);
75+
maze[entrance[0]][entrance[1]] = '+';
76+
while(!queue.isEmpty()){
77+
int n = queue.size();
78+
for(int i = 0; i < n; i++){
79+
int[] temp = queue.poll();
80+
if((temp[0] == maze.length - 1 || temp[1] == maze[0].length - 1 || temp[0] == 0 || temp[1] == 0) && (temp[0] != entrance[0] || temp[1] != entrance[1])) return ans;
81+
for(int[] array: dir){
82+
int x = temp[0] + array[0], y = temp[1] + array[1];
83+
if(x >= 0 && x < maze.length && y >= 0 && y < maze[0].length && maze[x][y] != '+'){
84+
queue.offer(new int[]{x, y});
85+
maze[x][y] = '+';
86+
}
87+
}
88+
}
89+
ans += 1;
90+
}
91+
return -1;
92+
}
93+
}
94+
```
95+
96+
补充一点,**广度优先搜索**大部分使用**非递归**的方法,**深度优先搜索**大部分使用**递归**的方法。
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
#### 1339. 分裂二叉树的最大乘积
2+
3+
难度:中等
4+
5+
-------
6+
7+
给你一棵二叉树,它的根为 `root` 。请你删除 1 条边,使二叉树分裂成两棵子树,且它们子树和的乘积尽可能大。
8+
9+
由于答案可能会很大,请你将结果对 10^9 + 7 取模后再返回。
10+
11+
**示例 1:**
12+
13+
**![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2020/02/02/sample_1_1699.png)**
14+
15+
```
16+
输入:root = [1,2,3,4,5,6]
17+
输出:110
18+
解释:删除红色的边,得到 2 棵子树,和分别为 11 和 10 。它们的乘积是 110 (11*10)
19+
```
20+
21+
**示例 2:**
22+
23+
![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2020/02/02/sample_2_1699.png)
24+
25+
```
26+
输入:root = [1,null,2,3,4,null,null,5,6]
27+
输出:90
28+
解释:移除红色的边,得到 2 棵子树,和分别是 15 和 6 。它们的乘积为 90 (15*6)
29+
```
30+
31+
**示例 3:**
32+
33+
```
34+
输入:root = [2,3,9,10,7,8,6,5,4,11,1]
35+
输出:1025
36+
```
37+
38+
**示例 4:**
39+
40+
```
41+
输入:root = [1,1]
42+
输出:1
43+
```
44+
45+
**提示:**
46+
47+
* 每棵树最多有 `50000` 个节点,且至少有 `2` 个节点。
48+
* 每个节点的值在 `[1, 10000]` 之间。
49+
50+
---
51+
52+
失败:
53+
54+
1. `MOD = (int) 1e9 + 7` !!!!
55+
56+
2. 应该是 `return ans % MOD`,而不是在每一次取最大值的时候取余
57+
58+
3. 需要用到 MOD 的时候最好使用 `long` 类型
59+
60+
61+
```java
62+
class Solution {
63+
private static final int MOD = (int) 10e9 + 7; // 低级错误!!!
64+
private int ans = 0, sum;
65+
public int maxProduct(TreeNode root) {
66+
sum = dfs(root);
67+
dfs2(root);
68+
return ans;
69+
}
70+
71+
private int dfs(TreeNode root){
72+
if(root == null) return 0;
73+
return dfs(root.left) + dfs(root.right) + root.val;
74+
}
75+
76+
private void dfs2(TreeNode root){
77+
if(root == null) return;
78+
int temp = dfs(root);
79+
ans = Math.max(ans, ((sum - temp) * temp) % MOD); // 不应该在此处取余
80+
dfs2(root.left);
81+
dfs2(root.right);
82+
}
83+
}
84+
```
85+
86+
失败:
87+
88+
1. 在递归中调用了递归,**嵌套的双重递归是十分消耗资源**的,从[这里](https://leetcode.cn/problems/maximum-product-of-splitted-binary-tree/solution/shi-gai-xiang-zui-da-hua-chu-shi-gen-jie-3cpw/)发现问题的。
89+
90+
91+
```java
92+
class Solution {
93+
private static final long MOD = (long) 1e9 + 7;
94+
private long ans = 0, sum;
95+
long test = 0;
96+
public int maxProduct(TreeNode root) {
97+
sum = dfs(root);
98+
dfs2(root);
99+
return (int) (ans % MOD);
100+
}
101+
102+
private long dfs(TreeNode root){
103+
if(root == null) return 0;
104+
return dfs(root.left) + dfs(root.right) + (long)root.val;
105+
}
106+
107+
private void dfs2(TreeNode root){
108+
if(root == null) return;
109+
long temp = dfs(root); // 双重递归,十分消耗资源!
110+
if(((sum - temp) * temp) % MOD > ans) test = temp ;
111+
ans = Math.max(ans, ((sum - temp) * temp));
112+
dfs2(root.left);
113+
dfs2(root.right);
114+
}
115+
}
116+
```
117+
118+
成功:
119+
120+
补充一点,嵌套的双重递归是自顶向下,每个递归的节点又自顶向下递归一遍,修改后的代码是自底向上的,每个结点只遍历一遍。
121+
122+
```java
123+
class Solution {
124+
private static final long MOD = (long) 1e9 + 7;
125+
private long ans = 0, sum;
126+
long test = 0;
127+
public int maxProduct(TreeNode root) {
128+
sum = dfs(root);
129+
dfs2(root);
130+
return (int) (ans % MOD);
131+
}
132+
133+
private long dfs(TreeNode root){
134+
if(root == null) return 0;
135+
return dfs(root.left) + dfs(root.right) + (long)root.val;
136+
}
137+
138+
private long dfs2(TreeNode root){
139+
if(root == null) return 0;
140+
long temp = dfs2(root.left) + dfs2(root.right) + root.val;
141+
ans = Math.max(ans, ((sum - temp) * temp));
142+
return temp;
143+
}
144+
}
145+
```

0 commit comments

Comments
 (0)