Skip to content

Commit 1fd0e22

Browse files
committed
update
1 parent 6331631 commit 1fd0e22

File tree

5 files changed

+267
-0
lines changed

5 files changed

+267
-0
lines changed

0085-最大矩形.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# 最大矩形
2+
3+
## 题目描述
4+
5+
给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。
6+
7+
```
8+
输入:
9+
[
10+
["1","0","1","0","0"],
11+
["1","0","1","1","1"],
12+
["1","1","1","1","1"],
13+
["1","0","0","1","0"]
14+
]
15+
输出: 6
16+
```
17+
18+
## 分析
19+
20+
动态规划。使用三个数组 `height` `left` `right` 保存每一行各点的向上、向左、向右延申的最大宽度。于是其组成的矩形就是最大矩形,使用一个变量保存最大值。
21+
22+
## 算法
23+
24+
```java
25+
class Solution {
26+
public int maximalRectangle(char[][] matrix) {
27+
int row, col;
28+
if(matrix == null || (row = matrix.length) == 0 || (col = matrix[0].length) == 0)
29+
return 0;
30+
31+
int[] height = new int[col];
32+
int[] left = new int[col];
33+
int[] right = new int[col];
34+
Arrays.fill(right, col);
35+
36+
int max = 0;
37+
38+
for(int i = 0; i < row; i++){
39+
int curLeft = 0, curRight = col;
40+
for(int j = col - 1; j >= 0; j--){
41+
if(matrix[i][j] == '1'){
42+
right[j] = Math.min(right[j], curRight);
43+
}else{
44+
right[j] = col; curRight = j;
45+
}
46+
}
47+
for(int j = 0; j < col; j++){
48+
if(matrix[i][j] == '1'){
49+
height[j]++;
50+
left[j] = Math.max(left[j], curLeft);
51+
}else{
52+
height[j] = 0;
53+
left[j] = 0; curLeft = j + 1;
54+
}
55+
max = Math.max(max, (right[j] - left[j]) * height[j]);
56+
}
57+
}
58+
return max;
59+
}
60+
```

0174-地下城游戏.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# 地下城游戏
2+
3+
## 题目描述
4+
5+
一些恶魔抓住了公主(P)并将她关在了地下城的右下角。地下城是由 `M x N` 个房间组成的二维网格。我们英勇的骑士(K)最初被安置在左上角的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。
6+
7+
骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。
8+
9+
有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为 0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。
10+
11+
为了尽快到达公主,骑士决定每次只向右或向下移动一步。
12+
13+
编写一个函数来计算确保骑士能够拯救到公主所需的最低初始健康点数。
14+
15+
例如,考虑到如下布局的地下城,如果骑士遵循最佳路径 `右 -> 右 -> 下 -> 下`,则骑士的初始健康点数至少为 `7`
16+
17+
```
18+
-2 (K) -3 3
19+
-5 -10 1
20+
10 30 -5 (P)
21+
```
22+
23+
* 骑士的健康点数没有上限。
24+
* 任何房间都可能对骑士的健康点数造成威胁,也可能增加骑士的健康点数,包括骑士进入的左上角房间以及公主被监禁的右下角房间。
25+
26+
## 分析
27+
28+
因为骑士只能向下或向右走,当骑士在最后一行时,如果安全的通过最后一行,其生命值只和最后一行的值相关。
29+
30+
同理,当骑士不在最后一行时,其生命值只和其当前行的剩余位置值以及下一行的值相关。所以可以从公主的位置开始,自底向上,循环更新骑士的生命值。骑士应选择扣生命值小的那一条路行走。
31+
32+
需要注意的是,当遇到生命值增加,且需要扣掉的生命值为正数时,应该将其归零,意思是骑士到这一格时只需1点生命值,即可遇到公主。
33+
最后将计算出的骑士在第一格的生命值取负加一,即为所需生命值。
34+
35+
## 算法
36+
37+
```java
38+
class Solution {
39+
public int calculateMinimumHP(int[][] dungeon) {
40+
int row = dungeon.length;
41+
int col = dungeon[0].length;
42+
43+
int []dp = new int[col];
44+
Arrays.fill(dp, Integer.MIN_VALUE);
45+
dp[col-1] = 0;
46+
47+
for(int i = row - 1; i >= 0; --i){
48+
dp[col-1] += dungeon[i][col-1];
49+
dp[col-1] = Math.min(dp[col-1], 0);
50+
51+
for(int j = col - 2; j >= 0; --j){
52+
dp[j] = Math.max(dp[j], dp[j+1]) + dungeon[i][j];
53+
dp[j] = Math.min(dp[j], 0);
54+
}
55+
}
56+
return 1 - dp[0];
57+
}
58+
}
59+
```

0312-戳气球.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# 戳气球
2+
3+
## 题目描述
4+
5+
`n` 个气球,编号为 `0``n-1`,每个气球上都标有一个数字,这些数字存在数组 `nums` 中。
6+
7+
现在要求你戳破所有的气球。每当你戳破一个气球 `i` 时,你可以获得 `nums[left] * nums[i] * nums[right]` 个硬币。 这里的 `left``right` 代表和 i 相邻的两个气球的序号。注意当你戳破了气球 `i` 后,气球 `left` 和气球 `right` 就变成了相邻的气球。
8+
9+
* 你可以假设 nums[-1] = nums[n] = 1,但注意它们不是真实存在的所以并不能被戳破。
10+
* 0 <= n <= 500, 0 <= nums[i] <= 100
11+
12+
```
13+
输入: [3,1,5,8]
14+
输出: 167
15+
解释: nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> []
16+
coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167
17+
```
18+
19+
## 分析
20+
21+
动态规划。`dp[i][j]` 表示戳破 `[i+1,...,j-1]` 号气球的最大收益。
22+
23+
假设 `k` 号气球(i+1 <= k <= j-1)是 `[i+1,...,j-1]` 中最后一个被戳破的,则 `dp[i][j] = max {for k = range(i+1, j -1) nums[i] * nums[k] * nums[j] + dp[i][k] + dp[k][j]}`
24+
25+
## 算法
26+
27+
```java
28+
class Solution {
29+
public int maxCoins(int[] nums) {
30+
int length = nums.length;
31+
int[] temp = new int[length+2];
32+
System.arraycopy(nums, 0, temp, 1, length);
33+
temp[0] = 1; temp[length+1] = 1;
34+
35+
int[][] dp = new int[temp.length][temp.length];
36+
37+
for(int len = 2; len < temp.length; ++len){
38+
for (int i = 0; i < temp.length - len; ++i) {
39+
int j = i + len;
40+
for (int k = i + 1; k < j; ++k) {
41+
dp[i][j] = Math.max(dp[i][j], temp[i] * temp[k] * temp[j] + dp[i][k] + dp[k][j]);
42+
}
43+
}
44+
}
45+
return dp[0][temp.length - 1];
46+
}
47+
}
48+
```

0337-打家劫舍 III.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# 打家劫舍 III
2+
3+
## 题目描述
4+
5+
在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。
6+
7+
计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。
8+
9+
```
10+
输入: [3,2,3,null,3,null,1]
11+
12+
3
13+
/ \
14+
2 3
15+
\ \
16+
3 1
17+
18+
输出: 7
19+
解释: 小偷一晚能够盗取的最高金额 = 3 + 3 + 1 = 7.
20+
21+
输入: [3,4,5,1,3,null,1]
22+
23+
3
24+
/ \
25+
4 5
26+
/ \ \
27+
1 3 1
28+
29+
输出: 9
30+
解释: 小偷一晚能够盗取的最高金额 = 4 + 5 = 9.
31+
```
32+
33+
## 分析
34+
35+
深度优先搜索。计算 `当前节点和子节点的子节点``子节点` 和的大小,取最大值即可。
36+
37+
## 算法
38+
39+
```java
40+
/**
41+
* Definition for a binary tree node.
42+
* public class TreeNode {
43+
* int val;
44+
* TreeNode left;
45+
* TreeNode right;
46+
* TreeNode(int x) { val = x; }
47+
* }
48+
*/
49+
class Solution {
50+
public int rob(TreeNode root) {
51+
if(root == null) return 0;
52+
int curValue = root.val;
53+
int sonValue = rob(root.left) + rob(root.right);
54+
if(root.left != null)
55+
curValue += (rob(root.left.left) + rob(root.left.right));
56+
if(root.right != null)
57+
curValue += (rob(root.right.left) + rob(root.right.right));
58+
59+
return Math.max(curValue, sonValue);
60+
}
61+
}
62+
```
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# 计算各个位数不同的数字个数
2+
3+
## 题目描述
4+
5+
给定一个非负整数 `n`,计算各位数字都不同的数字 `x` 的个数,其中 `0 <= x < 10^n`
6+
7+
```
8+
输入: 2
9+
输出: 91
10+
解释: 答案应为除去 11,22,33,44,55,66,77,88,99 外,在 [0,100) 区间内的所有数字。
11+
```
12+
13+
## 分析
14+
15+
写下前几个,就能看出规律了。
16+
17+
1. n=1: res=10
18+
2. n=2: res=9\*9+10=91 # 两位数第一位只能为1-9,第二位只能为非第一位的数,加上一位数的所有结果
19+
3. n=3: res=9\*9\*8+91=739 # 三位数第一位只能为1-9,第二位只能为非第一位的数,第三位只能为非前两位的数,加上两位数的所有结果
20+
4. n=4: res=9\*9\*8\*7+739=5275
21+
22+
## 算法
23+
24+
```java
25+
class Solution {
26+
public int countNumbersWithUniqueDigits(int n) {
27+
if(n == 0) return 1;
28+
int result = 10;
29+
int mul = 9;
30+
31+
for(int i = 2; i <= n; i++){
32+
mul *= (11 - i);
33+
result += mul;
34+
}
35+
return result;
36+
}
37+
}
38+
```

0 commit comments

Comments
 (0)