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

[pull] master from youngyangyang04:master #467

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
jenningsloy318 merged 2 commits into AlgorithmAndLeetCode:master from youngyangyang04:master
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@
5. [数组:209.长度最小的子数组](./problems/0209.长度最小的子数组.md)
6. [数组:区间和](./problems/kamacoder/0058.区间和.md)
6. [数组:59.螺旋矩阵II](./problems/0059.螺旋矩阵II.md)
7. [数组:总结篇](./problems/数组总结篇.md)
7. [数组:区间和](./problems/kamacoder/0058.区间和.md)
8. [数组:开发商购买土地](./problems/kamacoder/0044.开发商购买土地.md)
9. [数组:总结篇](./problems/数组总结篇.md)

## 链表

Expand Down
6 changes: 5 additions & 1 deletion problems/kamacoder/0044.开发商购买土地.md
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@

# 44. 开发商购买土地

> 本题为代码随想录后续扩充题目,还没有视频讲解,顺便让大家练习一下ACM输入输出模式(笔试面试必备)

[题目链接](https://kamacoder.com/problempage.php?pid=1044)

【题目描述】

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

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

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

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

Expand Down
16 changes: 10 additions & 6 deletions problems/kamacoder/0058.区间和.md
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

# 58. 区间和

> 本题为代码随想录后续扩充题目,还没有视频讲解,顺便让大家练习一下ACM输入输出模式(笔试面试必备)

[题目链接](https://kamacoder.com/problempage.php?pid=1070)

题目描述
Expand Down Expand Up @@ -97,27 +99,29 @@ int main() {

为什么呢?

p[1] = vec[0] + vec[1];
`p[1] = vec[0] + vec[1];`

p[5] = vec[0] + vec[1] + vec[2] + vec[3] + vec[4] + vec[5];
`p[5] = vec[0] + vec[1] + vec[2] + vec[3] + vec[4] + vec[5];`

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

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

如图所示:

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

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

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

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

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

很多录友在使用前缀和的时候,分不清前缀和的区间,建议画一画图,模拟一下 思路会更清晰。
**很多录友在使用前缀和的时候,分不清前缀和的区间,建议画一画图,模拟一下 思路会更清晰**。

本题C++代码如下:

```CPP
#include <iostream>
Expand Down
9 changes: 5 additions & 4 deletions problems/kamacoder/0098.所有可达路径.md
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,8 @@ int main() {
## 其他语言版本

### Java
#### 邻接矩阵写法

邻接矩阵写法
```java
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -477,7 +478,7 @@ public class Main {
}
```

#### 邻接表写法
邻接表写法
```java
import java.util.ArrayList;
import java.util.LinkedList;
Expand Down Expand Up @@ -533,7 +534,7 @@ public class Main {
}
```
### Python
#### 邻接矩阵写法
邻接矩阵写法
``` python
def dfs(graph, x, n, path, result):
if x == n:
Expand Down Expand Up @@ -566,7 +567,7 @@ if __name__ == "__main__":
main()
```

#### 邻接表写法
邻接表写法
``` python
from collections import defaultdict

Expand Down
1 change: 1 addition & 0 deletions problems/kamacoder/0109.冗余连接II.md
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ int main() {
vec.push_back(i);
}
}
// 情况一、情况二
if (vec.size() > 0) {
// 放在vec里的边已经按照倒叙放的,所以这里就优先删vec[0]这条边
if (isTreeAfterRemoveEdge(edges, vec[0])) {
Expand Down
59 changes: 59 additions & 0 deletions problems/kamacoder/0113.国际象棋.md
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@

# 113.国际象棋

广搜,但本题如果广搜枚举马和象的话会超时。

广搜要只枚举马的走位,同时判断是否在对角巷直接走象

```CPP
#include <iostream>
using namespace std;
const int N = 100005, mod = 1000000007;
using ll = long long;
int n, ans;
int dir[][2] = {{1, 2}, {1, -2}, {-1, 2}, {-1, -2}, {2, 1}, {2, -1}, {-2, -1}, {-2, 1}};
int main() {
int x1, y1, x2, y2;
cin >> n;
while (n--) {
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
if (x1 == x2 && y1 == y2) {
cout << 0 << endl;
continue;
}
// 判断象走一步到达
int d = abs(x1 - x2) - abs(y1 - y2);
if (!d) {cout << 1 << endl; continue;}
// 判断马走一步到达
bool one = 0;
for (int i = 0; i < 8; ++i) {
int dx = x1 + dir[i][0], dy = y1 + dir[i][1];
if (dx == x2 && dy == y2) {
cout << 1 << endl;
one = true;
break;
}
}
if (one) continue;
// 接下来为两步的逻辑, 象走两步或者马走一步,象走一步
// 象直接两步可以到达,这个计算是不是同颜色的格子,象可以在两步到达所有同颜色的格子
int d2 = abs(x1 - x2) + abs(y1 - y2);
if (d2 % 2 == 0) {
cout << 2 << endl;
continue;
}
// 接下来判断马 + 象的组合
bool two = 0;
for (int i = 0; i < 8; ++i) {
int dx = x1 + dir[i][0], dy = y1 + dir[i][1];
int d = abs(dx - x2) - abs(dy - y2);
if (!d) {cout << 2 << endl; two = true; break;}
}
if (two) continue;
// 剩下的格子全都是三步到达的
cout << 3 << endl;
}
return 0;
}

```
132 changes: 132 additions & 0 deletions problems/kamacoder/0121.小红的区间翻转.md
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@

# 121. 小红的区间翻转

比较暴力的方式,就是直接模拟, 枚举所有 区间,然后检查其翻转的情况。

在检查翻转的时候,需要一些代码优化,否则容易超时。

```CPP
#include <iostream>
#include <vector>
using namespace std;

bool canTransform(const vector<int>& a, const vector<int>& b, int left, int right) {
// 提前检查翻转区间的值是否可以匹配
for (int i = left, j = right; i <= right; i++, j--) {
if (a[i] != b[j]) {
return false;
}
}
// 检查翻转区间外的值是否匹配
for (int i = 0; i < left; i++) {
if (a[i] != b[i]) {
return false;
}
}
for (int i = right + 1; i < a.size(); i++) {
if (a[i] != b[i]) {
return false;
}
}
return true;
}

int main() {
int n;
cin >> n;

vector<int> a(n);
vector<int> b(n);

for (int i = 0; i < n; i++) {
cin >> a[i];
}

for (int i = 0; i < n; i++) {
cin >> b[i];
}

int count = 0;

// 遍历所有可能的区间
for (int left = 0; left < n; left++) {
for (int right = left; right < n; right++) {
// 检查翻转区间 [left, right] 后,a 是否可以变成 b
if (canTransform(a, b, left, right)) {
count++;
}
}
}
cout << count << endl;
return 0;
}
```

也可以事先计算好,最长公共前缀,和最长公共后缀。

在公共前缀和公共后缀之间的部分进行翻转操作,这样我们可以减少很多不必要的翻转尝试。

通过在公共前缀和后缀之间的部分,找到可以通过翻转使得 a 和 b 相等的区间。

以下 为评论区 卡码网用户:码鬼的C++代码

```CPP
#include <iostream>
#include <vector>

using namespace std;

int main() {
int n;
cin >> n;
vector<int> a(n), b(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
for (int i = 0; i < n; i++) {
cin >> b[i];
}

vector<int> prefix(n, 0), suffix(n, 0);

// 计算前缀相等的位置
int p = 0;
while (p < n && a[p] == b[p]) {
prefix[p] = 1;
p++;
}

// 计算后缀相等的位置
int s = n - 1;
while (s >= 0 && a[s] == b[s]) {
suffix[s] = 1;
s--;
}

int count = 0;

// 遍历所有可能的区间
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
// 判断前缀和后缀是否相等
if ((i == 0 || prefix[i - 1] == 1) && (j == n - 1 || suffix[j + 1] == 1)) {
// 判断翻转后的子数组是否和目标数组相同
bool is_palindrome = true;
for (int k = 0; k <= (j - i) / 2; k++) {
if (a[i + k] != b[j - k]) {
is_palindrome = false;
break;
}
}
if (is_palindrome) {
count++;
}
}
}
}

cout << count << endl;

return 0;
}
```
Loading

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