今天我们将在豆包MarsCode AI刷题平台上,完成《小S的黑白块迷宫》与《小U的数组权值计算》这两个算法问题,通过这些练习提升用户解决此类问题的能力
《小S的黑白块迷宫》题面如下:
问题理解
我们需要在一个 n x m 的网格迷宫中,从左上角 (0, 0) 移动到右下角 (n-1, m-1),并且希望在移动过程中经过的黑色格子(值为1)尽可能少。移动时可以向上、下、左、右四个方向移动,但不能走出迷宫的边界。
解题思路
-
数据结构选择:
- 使用一个二维数组
cache来记录从起点到每个格子的最少黑色格子数量。 - 使用一个队列
q来实现广度优先搜索(BFS),以确保我们找到的是最短路径。
- 使用一个二维数组
-
初始化:
- 将
cache数组初始化为一个较大的值(n * m + 1),表示初始状态下无法到达这些格子。 - 将起点
(0, 0)加入队列,并将其对应的cache值设置为grid[0][0]的值(即起点格子的值)。
- 将
-
广度优先搜索(BFS) :
- 从队列中取出当前格子
cur,并检查其四个相邻格子。 - 对于每个相邻格子
(nx, ny),检查是否越界。如果越界,则跳过。 - 如果当前路径经过的黑色格子数量(
cur[2])加上相邻格子的值grid[nx][ny]小于cache[nx][ny],则更新cache[nx][ny]并将其加入队列。
- 从队列中取出当前格子
-
返回结果:
- 最终,
cache[n-1][m-1]即为从起点到终点的最少黑色格子数量。
- 最终,
具体实现
import java.util.*;
public class Main {
static int[][] path = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public static int solution(int n, int m, int[][] grid) {
// write code here
int[][] cache = new int[n][m];
for (int[] row : cache) {
Arrays.fill(row, n * m + 1);
}
Queue<int[]> q = new LinkedList<>();
q.offer(new int[]{0, 0, grid[0][0]});
cache[0][0] = grid[0][0];
while (!q.isEmpty()) {
int[] cur = q.poll();
for (int i = 0; i < 4; i++) {
int nx = cur[0] + path[i][0], ny = cur[1] + path[i][1];
if (nx < 0 || nx >= n || ny < 0 || ny >= m) {
continue;
}
if (cache[nx][ny] <= cur[2] + grid[nx][ny]) {
continue;
}
cache[nx][ny] = cur[2] + grid[nx][ny];
q.offer(new int[]{nx, ny, cache[nx][ny]});
}
}
return cache[n - 1][m - 1];
}
public static void main(String[] args) {
System.out.println(solution(5, 3, new int[][]{{0, 1, 0}, {0, 1, 1}, {0, 1, 0}, {1, 0, 0}, {1, 0, 0}}) == 1);
System.out.println(solution(4, 4, new int[][]{{0, 0, 1, 0}, {1, 0, 1, 0}, {1, 0, 0, 0}, {1, 1, 1, 0}}) == 0);
System.out.println(solution(3, 3, new int[][]{{0, 0, 0}, {1, 1, 0}, {1, 1, 0}}) == 0);
}
}
《小U的数组权值计算》题面如下:
问题理解
我们需要计算由1到n的所有排列的“权值”之和。权值定义为相邻两数乘积为奇数的对数。由于乘积为奇数,意味着这两个数都必须是奇数。
关键点
-
奇数和偶数的分布:
- 在1到n的排列中,奇数的数量是
(n + 1) / 2。 - 偶数的数量是
n / 2。
- 在1到n的排列中,奇数的数量是
-
排列的生成:
- 我们需要考虑所有排列中相邻两数乘积为奇数的情况。
解题思路
-
计算奇数的数量:
- 奇数的数量可以通过
(n + 1) / 2计算得到。
- 奇数的数量可以通过
-
计算排列的权值:
- 对于每个排列,我们需要计算相邻两数乘积为奇数的对数。
- 由于乘积为奇数意味着两个数都是奇数,我们可以先计算奇数的排列方式,然后计算相邻奇数的对数。
-
其余数的排列的总数:
- 其余数的排列的总数是
(n - 2 + 1)!。
- 其余数的排列的总数是
具体实现
public class Main {
public static final int MOD = 1000000007;
public static int solution(int n) {
// 计算奇数的数量
int odd = (n + 1) / 2;
// 计算排列的权值
// 计算相邻奇数的对数
int pairs = odd * (odd - 1);
// 计算排列的总数
int totalPermutations = factorial(n - 2 + 1);
// 计算权值之和
int result = (int)((long)pairs * totalPermutations % MOD);
return result;
}
public static int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; i++) {
result = (int)((long)result * i % MOD);
}
return result;
}
public static void main(String[] args) {
System.out.println(solution(5) == 144);
System.out.println(solution(3) == 4);
System.out.println(solution(6) == 720);
}
}
借助豆包MarsCode AI刷题平台,我们不仅高效地解决了《小S的黑白块迷宫》和《小U的数组权值计算》,还加深了对相关算法和数据结构的理解,后续会借助豆包MarsCode AI给大家展示更多题目的解法