《小S的黑白块迷宫》和《小U的数组权值计算》| 豆包MarsCode AI刷题

173 阅读4分钟

今天我们将在豆包MarsCode AI刷题平台上,完成《小S的黑白块迷宫》与《小U的数组权值计算》这两个算法问题,通过这些练习提升用户解决此类问题的能力

《小S的黑白块迷宫》题面如下:

图片.png

问题理解

我们需要在一个 n x m 的网格迷宫中,从左上角 (0, 0) 移动到右下角 (n-1, m-1),并且希望在移动过程中经过的黑色格子(值为1)尽可能少。移动时可以向上、下、左、右四个方向移动,但不能走出迷宫的边界。

解题思路

  1. 数据结构选择

    • 使用一个二维数组 cache 来记录从起点到每个格子的最少黑色格子数量。
    • 使用一个队列 q 来实现广度优先搜索(BFS),以确保我们找到的是最短路径。
  2. 初始化

    • cache 数组初始化为一个较大的值(n * m + 1),表示初始状态下无法到达这些格子。
    • 将起点 (0, 0) 加入队列,并将其对应的 cache 值设置为 grid[0][0] 的值(即起点格子的值)。
  3. 广度优先搜索(BFS)

    • 从队列中取出当前格子 cur,并检查其四个相邻格子。
    • 对于每个相邻格子 (nx, ny),检查是否越界。如果越界,则跳过。
    • 如果当前路径经过的黑色格子数量(cur[2])加上相邻格子的值 grid[nx][ny] 小于 cache[nx][ny],则更新 cache[nx][ny] 并将其加入队列。
  4. 返回结果

    • 最终,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的数组权值计算》题面如下:

图片.png

问题理解

我们需要计算由1到n的所有排列的“权值”之和。权值定义为相邻两数乘积为奇数的对数。由于乘积为奇数,意味着这两个数都必须是奇数。

关键点

  1. 奇数和偶数的分布

    • 在1到n的排列中,奇数的数量是 (n + 1) / 2
    • 偶数的数量是 n / 2
  2. 排列的生成

    • 我们需要考虑所有排列中相邻两数乘积为奇数的情况。

解题思路

  1. 计算奇数的数量

    • 奇数的数量可以通过 (n + 1) / 2 计算得到。
  2. 计算排列的权值

    • 对于每个排列,我们需要计算相邻两数乘积为奇数的对数。
    • 由于乘积为奇数意味着两个数都是奇数,我们可以先计算奇数的排列方式,然后计算相邻奇数的对数。
  3. 其余数的排列的总数

    • 其余数的排列的总数是 (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给大家展示更多题目的解法