Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 2d9604b

Browse files
Update
1 parent 717ad84 commit 2d9604b

20 files changed

+991
-232
lines changed

‎README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,9 @@
107107
5. [数组:209.长度最小的子数组](./problems/0209.长度最小的子数组.md)
108108
6. [数组:区间和](./problems/kamacoder/0058.区间和.md)
109109
6. [数组:59.螺旋矩阵II](./problems/0059.螺旋矩阵II.md)
110-
7. [数组:总结篇](./problems/数组总结篇.md)
110+
7. [数组:区间和](./problems/kamacoder/0058.区间和.md)
111+
8. [数组:开发商购买土地](./problems/kamacoder/0044.开发商购买土地.md)
112+
9. [数组:总结篇](./problems/数组总结篇.md)
111113

112114
## 链表
113115

‎problems/kamacoder/0044.开发商购买土地.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11

22
# 44. 开发商购买土地
33

4+
> 本题为代码随想录后续扩充题目,还没有视频讲解,顺便让大家练习一下ACM输入输出模式(笔试面试必备)
5+
6+
[题目链接](https://kamacoder.com/problempage.php?pid=1044)
7+
48
【题目描述】
59

610
在一个城市区域内,被划分成了n * m个连续的区块,每个区块都拥有不同的权值,代表着其土地价值。目前,有两家开发公司,A 公司和 B 公司,希望购买这个城市区域的土地。
@@ -57,7 +61,7 @@
5761

5862
如果本题要求 任何两个行(或者列)之间的数值总和,大家在[0058.区间和](./0058.区间和.md) 的基础上 应该知道怎么求。
5963

60-
就是前缀和的思路,先统计好,前n行的和 q[n],如果要求矩阵 a 行到 b行 之间的总和,那么就 q[b] - q[a - 1]就好。
64+
就是前缀和的思路,先统计好,前n行的和 q[n],如果要求矩阵 a行 到 b行 之间的总和,那么就 q[b] - q[a - 1]就好。
6165

6266
至于为什么是 a - 1,大家去看 [0058.区间和](./0058.区间和.md) 的分析,使用 前缀和 要注意 区间左右边的开闭情况。
6367

‎problems/kamacoder/0058.区间和.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11

22
# 58. 区间和
33

4+
> 本题为代码随想录后续扩充题目,还没有视频讲解,顺便让大家练习一下ACM输入输出模式(笔试面试必备)
5+
46
[题目链接](https://kamacoder.com/problempage.php?pid=1070)
57

68
题目描述
@@ -97,27 +99,29 @@ int main() {
9799

98100
为什么呢?
99101

100-
p[1] = vec[0] + vec[1];
102+
`p[1] = vec[0] + vec[1];`
101103

102-
p[5] = vec[0] + vec[1] + vec[2] + vec[3] + vec[4] + vec[5];
104+
`p[5] = vec[0] + vec[1] + vec[2] + vec[3] + vec[4] + vec[5];`
103105

104-
p[5] - p[1] = vec[2] + vec[3] + vec[4] + vec[5];
106+
`p[5] - p[1] = vec[2] + vec[3] + vec[4] + vec[5];`
105107

106108
这不就是我们要求的 下标 2 到下标 5 之间的累加和吗。
107109

108110
如图所示:
109111

110112
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20240627111319.png)
111113

112-
p[5] - p[1] 就是 红色部分的区间和。
114+
`p[5] - p[1]` 就是 红色部分的区间和。
113115

114-
而 p 数组是我们之前就计算好的累加和,所以后面每次求区间和的之后 我们只需要 O(1)的操作。
116+
而 p 数组是我们之前就计算好的累加和,所以后面每次求区间和的之后 我们只需要 O(1)的操作。
115117

116118
**特别注意**: 在使用前缀和求解的时候,要特别注意 求解区间。
117119

118120
如上图,如果我们要求 区间下标 [2, 5] 的区间和,那么应该是 p[5] - p[1],而不是 p[5] - p[2]
119121

120-
很多录友在使用前缀和的时候,分不清前缀和的区间,建议画一画图,模拟一下 思路会更清晰。
122+
**很多录友在使用前缀和的时候,分不清前缀和的区间,建议画一画图,模拟一下 思路会更清晰**
123+
124+
本题C++代码如下:
121125

122126
```CPP
123127
#include <iostream>

‎problems/kamacoder/0098.所有可达路径.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,8 @@ int main() {
422422
## 其他语言版本
423423

424424
### Java
425-
#### 邻接矩阵写法
425+
426+
邻接矩阵写法
426427
```java
427428
import java.util.ArrayList;
428429
import java.util.List;
@@ -477,7 +478,7 @@ public class Main {
477478
}
478479
```
479480

480-
#### 邻接表写法
481+
邻接表写法
481482
```java
482483
import java.util.ArrayList;
483484
import java.util.LinkedList;
@@ -533,7 +534,7 @@ public class Main {
533534
}
534535
```
535536
### Python
536-
#### 邻接矩阵写法
537+
邻接矩阵写法
537538
``` python
538539
def dfs(graph, x, n, path, result):
539540
if x == n:
@@ -566,7 +567,7 @@ if __name__ == "__main__":
566567
main()
567568
```
568569

569-
#### 邻接表写法
570+
邻接表写法
570571
``` python
571572
from collections import defaultdict
572573

‎problems/kamacoder/0109.冗余连接II.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ int main() {
225225
vec.push_back(i);
226226
}
227227
}
228+
// 情况一、情况二
228229
if (vec.size() > 0) {
229230
// 放在vec里的边已经按照倒叙放的,所以这里就优先删vec[0]这条边
230231
if (isTreeAfterRemoveEdge(edges, vec[0])) {

‎problems/kamacoder/0113.国际象棋.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
2+
# 113.国际象棋
3+
4+
广搜,但本题如果广搜枚举马和象的话会超时。
5+
6+
广搜要只枚举马的走位,同时判断是否在对角巷直接走象
7+
8+
```CPP
9+
#include <iostream>
10+
using namespace std;
11+
const int N = 100005, mod = 1000000007;
12+
using ll = long long;
13+
int n, ans;
14+
int dir[][2] = {{1, 2}, {1, -2}, {-1, 2}, {-1, -2}, {2, 1}, {2, -1}, {-2, -1}, {-2, 1}};
15+
int main() {
16+
int x1, y1, x2, y2;
17+
cin >> n;
18+
while (n--) {
19+
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
20+
if (x1 == x2 && y1 == y2) {
21+
cout << 0 << endl;
22+
continue;
23+
}
24+
// 判断象走一步到达
25+
int d = abs(x1 - x2) - abs(y1 - y2);
26+
if (!d) {cout << 1 << endl; continue;}
27+
// 判断马走一步到达
28+
bool one = 0;
29+
for (int i = 0; i < 8; ++i) {
30+
int dx = x1 + dir[i][0], dy = y1 + dir[i][1];
31+
if (dx == x2 && dy == y2) {
32+
cout << 1 << endl;
33+
one = true;
34+
break;
35+
}
36+
}
37+
if (one) continue;
38+
// 接下来为两步的逻辑, 象走两步或者马走一步,象走一步
39+
// 象直接两步可以到达,这个计算是不是同颜色的格子,象可以在两步到达所有同颜色的格子
40+
int d2 = abs(x1 - x2) + abs(y1 - y2);
41+
if (d2 % 2 == 0) {
42+
cout << 2 << endl;
43+
continue;
44+
}
45+
// 接下来判断马 + 象的组合
46+
bool two = 0;
47+
for (int i = 0; i < 8; ++i) {
48+
int dx = x1 + dir[i][0], dy = y1 + dir[i][1];
49+
int d = abs(dx - x2) - abs(dy - y2);
50+
if (!d) {cout << 2 << endl; two = true; break;}
51+
}
52+
if (two) continue;
53+
// 剩下的格子全都是三步到达的
54+
cout << 3 << endl;
55+
}
56+
return 0;
57+
}
58+
59+
```
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
2+
# 121. 小红的区间翻转
3+
4+
比较暴力的方式,就是直接模拟, 枚举所有 区间,然后检查其翻转的情况。
5+
6+
在检查翻转的时候,需要一些代码优化,否则容易超时。
7+
8+
```CPP
9+
#include <iostream>
10+
#include <vector>
11+
using namespace std;
12+
13+
bool canTransform(const vector<int>& a, const vector<int>& b, int left, int right) {
14+
// 提前检查翻转区间的值是否可以匹配
15+
for (int i = left, j = right; i <= right; i++, j--) {
16+
if (a[i] != b[j]) {
17+
return false;
18+
}
19+
}
20+
// 检查翻转区间外的值是否匹配
21+
for (int i = 0; i < left; i++) {
22+
if (a[i] != b[i]) {
23+
return false;
24+
}
25+
}
26+
for (int i = right + 1; i < a.size(); i++) {
27+
if (a[i] != b[i]) {
28+
return false;
29+
}
30+
}
31+
return true;
32+
}
33+
34+
int main() {
35+
int n;
36+
cin >> n;
37+
38+
vector<int> a(n);
39+
vector<int> b(n);
40+
41+
for (int i = 0; i < n; i++) {
42+
cin >> a[i];
43+
}
44+
45+
for (int i = 0; i < n; i++) {
46+
cin >> b[i];
47+
}
48+
49+
int count = 0;
50+
51+
// 遍历所有可能的区间
52+
for (int left = 0; left < n; left++) {
53+
for (int right = left; right < n; right++) {
54+
// 检查翻转区间 [left, right] 后,a 是否可以变成 b
55+
if (canTransform(a, b, left, right)) {
56+
count++;
57+
}
58+
}
59+
}
60+
cout << count << endl;
61+
return 0;
62+
}
63+
```
64+
65+
也可以事先计算好,最长公共前缀,和最长公共后缀。
66+
67+
在公共前缀和公共后缀之间的部分进行翻转操作,这样我们可以减少很多不必要的翻转尝试。
68+
69+
通过在公共前缀和后缀之间的部分,找到可以通过翻转使得 a 和 b 相等的区间。
70+
71+
以下 为评论区 卡码网用户:码鬼的C++代码
72+
73+
```CPP
74+
#include <iostream>
75+
#include <vector>
76+
77+
using namespace std;
78+
79+
int main() {
80+
int n;
81+
cin >> n;
82+
vector<int> a(n), b(n);
83+
for (int i = 0; i < n; i++) {
84+
cin >> a[i];
85+
}
86+
for (int i = 0; i < n; i++) {
87+
cin >> b[i];
88+
}
89+
90+
vector<int> prefix(n, 0), suffix(n, 0);
91+
92+
// 计算前缀相等的位置
93+
int p = 0;
94+
while (p < n && a[p] == b[p]) {
95+
prefix[p] = 1;
96+
p++;
97+
}
98+
99+
// 计算后缀相等的位置
100+
int s = n - 1;
101+
while (s >= 0 && a[s] == b[s]) {
102+
suffix[s] = 1;
103+
s--;
104+
}
105+
106+
int count = 0;
107+
108+
// 遍历所有可能的区间
109+
for (int i = 0; i < n - 1; i++) {
110+
for (int j = i + 1; j < n; j++) {
111+
// 判断前缀和后缀是否相等
112+
if ((i == 0 || prefix[i - 1] == 1) && (j == n - 1 || suffix[j + 1] == 1)) {
113+
// 判断翻转后的子数组是否和目标数组相同
114+
bool is_palindrome = true;
115+
for (int k = 0; k <= (j - i) / 2; k++) {
116+
if (a[i + k] != b[j - k]) {
117+
is_palindrome = false;
118+
break;
119+
}
120+
}
121+
if (is_palindrome) {
122+
count++;
123+
}
124+
}
125+
}
126+
}
127+
128+
cout << count << endl;
129+
130+
return 0;
131+
}
132+
```

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /