华为OD机试真题---学生方阵

华为OD机试真题中的“学生方阵”题目是一道有趣的编程挑战。以下是对该题目的详细解析:

一、题目描述

学校组织活动,将学生排成一个矩形方阵。题目要求在矩形方阵中找到最大的位置相连的男生数量,这个相连位置在一个直线上,方向可以是水平的、垂直的、成对角线的或者呈反对角线的。

注:学生个数不会超过10000

二、输入描述

  • 输入的第一行为矩阵的行数和列数,接下来的n行为矩阵元素,元素间用”,”分隔。
  • 接下来的n行为矩阵元素,元素间用逗号分隔。矩阵中的元素表示学生的性别,“M”代表男生,“F”代表女生。

三、输出描述

输出一个整数,表示矩阵中最长的位置相连的男生个数。

示例
输入

3,4
F,M,M,F
F,M,M,F
F,F,F,M

输出

3

输入

1,2
M,M

输出

2

输入

2,1
M
F

输出

1

四、解题思路

  1. 遍历矩阵:首先,需要遍历矩阵中的每一个元素,以每一个“M”(男生)作为起点,开始寻找相连的男生数量。
  2. 定义方向:为了找到所有可能相连的男生,需要定义四个方向(水平、垂直、正对角线、反对角线)进行搜索。这可以通过一个二维方向数组来实现。
  3. 深度优先遍历:从每一个男生起点开始,沿着上述四个方向进行深度优先遍历,记录每个方向上相连的男生数量,并保留最大值。
  4. 更新结果:在遍历过程中,不断更新找到的最大相连男生数量。

五、示例代码



import java.util.Scanner;

public class StudentSquare {
    static int[][] directions = {{0, 1}, {1, 1}, {1, 0}, {1, -1}}; // 方向数组,分别表示右、右下、下、左下

    /**
     * 主函数,用于寻找矩阵中从男生(M)出发的最大路径长度
     */
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        // 读取并解析输入的矩阵行列数
        String[] input = scanner.nextLine().split(",");
        int m = Integer.parseInt(input[0]); // 矩阵行数
        int n = Integer.parseInt(input[1]); // 矩阵列数
        String[][] matrix = new String[m][n];
    
        // 读取矩阵
        for (int i = 0; i < m; i++) {
            String[] line = scanner.nextLine().split(",");
            for (int j = 0; j < n; j++) {
                matrix[i][j] = line[j];
            }
        }
    
        // 初始化最大路径长度为0
        int maxLen = 0;
        // 遍历矩阵中的每一个男生
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (matrix[i][j].equals("M")) {
                    int len = 0;
                    // 对每一个方向进行深度优先遍历
                    for (int[] dir : directions) {
                        len = Math.max(len, getMaxLength(matrix, i, j, dir[0], dir[1]));
                    }
                    maxLen = Math.max(maxLen, len);
                }
            }
        }
    
        // 输出最大路径长度
        System.out.println(maxLen);
    }

    // 使用深度优先遍历算法获取相连男生的最大数量
    // 该方法递归地检查在一个矩阵中,从某个起点开始,沿着指定方向,连续的男生("M")的最大数量
    private static int getMaxLength(String[][] matrix, int x, int y, int dx, int dy) {
        // 获取矩阵的行数和列数
        int m = matrix.length;
        int n = matrix[0].length;
        // 检查当前位置是否超出矩阵边界,或者当前位置不是男生("M")
        if (x < 0 || x >= m || y < 0 || y >= n || !matrix[x][y].equals("M")) {
            // 如果条件满足,说明当前位置无效或不是男生,返回0,表示没有相连的男生
            return 0;
        }
        // 如果当前位置是男生("M"),则递归地向指定方向移动一步,并累加计数
        // 通过递归调用自身,不断沿dx和dy方向前进,直到不满足条件时,返回累加的数量
        return 1 + getMaxLength(matrix, x + dx, y + dy, dx, dy);
    }
}

六、运行示例解析

输入

3,4
F,M,M,F
F,M,M,F
F,F,F,M

步骤解析

  1. 初始化

    • 读取输入的行数 m = 3 和列数 n = 4
    • 创建一个 3x4 的字符串矩阵 matrix
  2. 读取矩阵

    • 根据输入,填充矩阵 matrix 如下:
      [
        ["F", "M", "M", "F"],
        ["F", "M", "M", "F"],
        ["F", "F", "F", "M"]
      ]
      
  3. 遍历矩阵

    • 从矩阵的每一个位置 (i, j) 开始,如果位置上是男生 "M",则进行深度优先遍历。
  4. 深度优先遍历

    • 从每个男生位置 (i, j) 开始,沿着四个方向(右、右下、下、左下)进行遍历。
    • 使用递归函数 getMaxLength 计算从当前位置开始,沿着指定方向可以连续遇到的男生数量。
  5. 计算最大路径长度

    • 对于每个男生位置 (i, j),计算其在四个方向上的最大路径长度,并更新全局最大路径长度 maxLen

详细解析

  • 对于位置 (0, 1)(即第一行第二列的男生 "M"):

    • 向右(方向 {0, 1}):连续两个 "M",长度为 2。
    • 向右下(方向 {1, 1}):第一个方向是 (1, 2)"M",但第二个方向 (2, 3)"F",长度为 1。
    • 向下(方向 {1, 0}):超出边界。
    • 向左下(方向 {1, -1}):第一个方向是 (1, 0)"F",长度为 0。
    • 对于 (0, 1) 的最大路径长度为 2。
  • 对于位置 (1, 1)(即第二行第二列的男生 "M"):

    • 向右(方向 {0, 1}):连续两个 "M",长度为 2。
    • 向右下(方向 {1, 1}):第一个方向是 (2, 2)"M",但第二个方向 (3, 3) 超出边界,长度为 2。
    • 向下(方向 {1, 0}):超出边界。
    • 向左下(方向 {1, -1}):第一个方向是 (2, 0)"F",长度为 0。
    • 对于 (1, 1) 的最大路径长度为 2。
  • 对于其他男生位置,进行类似的计算。

  • 最终,全局最大路径长度 maxLen 是 3,因为从 (1, 1) 向右下方向 (2, 2)(1, 2) 可以连续遇到三个男生 "M"

输出

3

注意:在给出的代码中,方向数组和递归逻辑是正确的,但需要注意的是,题目中要求的是“最大的位置相连的男生数量”,而不仅仅是某个方向上的连续男生数量。因此,理论上应该对每个男生位置 (i, j) 进行四个方向的搜索,并考虑所有可能的路径(包括回头和变向),但这样做复杂度会非常高。在实际情况下,为了简化问题,通常只考虑单向(不回头)的连续路径长度,如上述解析所示。如果要考虑所有可能的路径组合,则需要使用更复杂的算法(如动态规划或回溯算法),并可能需要对每个位置进行多次访问和标记。然而,对于本题目的简单解法,上述解析已经足够。


六、注意事项

  1. 边界条件:在遍历过程中,需要注意边界条件,避免数组越界。
  2. 效率优化:由于矩阵的大小可能达到10000x10000,因此需要考虑算法的效率。上述代码使用了深度优先遍历,但在实际应用中,可能需要考虑使用动态规划或其他优化算法来提高效率。
  3. 输入验证:在实际应用中,还需要对输入进行验证,确保输入的数据符合题目要求。

综上所述,华为OD机试真题中的“学生方阵”题目是一道考察矩阵遍历和深度优先遍历的编程题。通过理解题目要求、定义方向数组、进行深度优先遍历以及更新结果等步骤,可以求解出矩阵中最长的位置相连的男生数量。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值