华为OD-机试

发布时间 2023-08-27 22:22:24作者: YaosGHC

B 卷

100 分题 1:支持优先级的队列

实现一个支持优先级的队列,高优先级先出队列,同优先级时先进先出。
如果两个输入数据和优先级都相同,则后一个数据不入队列被丢弃。
队列存储的数据内容是一个整数。

输入描述:一组待存入队列的数据(包含内容和优先级)。

输出描述:队列的数据内容(优先级信息输出时不再体现)。

补充说明:不用考虑数据不合法的情况,测试数据不超过100个。

示例1
输入:(10,1),(20,1),(30,2),(40,3)

输出:40,30,10,20

说明:
输入样例中,向队列写入了4个数据,每个数据由数据内容和优先级组成。输入和输出内容都不含空格。
数据40的优先级最高,所以最先输出,其次是30:10和20优先级相同,所以按输入顺序输出

示例2
输入:(10,1),(10,1),(30,2),(40,3)

输出:40,30,10

说明:数据40的优先级最高,所以最先输出,其次是30;两个10和10构成重复数据,被丢弃一个。

/**
 * 优先队列节点定义
 */
class PriorityQueueItem {
    int data;
    int priority;

    public PriorityQueueItem(int data, int priority) {
        this.data = data;
        this.priority = priority;
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        List<PriorityQueueItem> queue = new ArrayList<>();
        /*
        获取并处理输入:获取一整行字符串并拆分提取数据
         */
        while (in.hasNext()) {
            String[] element = in.next().split(",");
            for (int i = 0; i < element.length; i += 2) {
                int data = Integer.parseInt(element[i].substring(1));
                int priority = Integer.parseInt(element[i + 1].substring(0, element[1].length() - 1));
                addToQueue(queue, data, priority);
            }
        }
        /*
        打印
         */
        for (int i = 0; i < queue.size(); i++) {
            if (i == queue.size() - 1) System.out.print(queue.get(i).data);
            else System.out.print(queue.get(i).data + ",");
        }
    }

    private static void addToQueue(List<PriorityQueueItem> queue, int data, int priority) {
        // 排除重复元素
        for (PriorityQueueItem item : queue) {
            if (item.data == data && item.priority == priority) return;
        }
        // 遍历整个优先队列,如果优先级小于准备插入的节点,就将节点插入到当前位置
        // 为了实现相同优先级先进入的先插入,则只能是 >
        // 这里并不适合改成二分查找,因为并不是找一个确定的位置,而是找第一个优先级更小的位置
        for (int i = 0; i < queue.size(); i++) {
            if (priority > queue.get(i).priority) {
                queue.add(i, new PriorityQueueItem(data, priority));
                return;
            }
        }
        queue.add(new PriorityQueueItem(data, priority));
    }
}

100 分题 2:计算最大乘积

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String[] arr = in.nextLine().split(",");
        int max = 0;
        /*
        两两检查
         */
        for (int i = 0; i < arr.length; i++) {
            for (int j = i + 1; j < arr.length; j++) {
                if (!check(arr[i], arr[j])) max = Math.max(max, arr[i].length() * arr[j].length());
            }
        }
        System.out.println(max);
    }

    /**
     * 检查两个字符串中是否有相同的字符
     * 转化为字符数组并排序,每次移动较小的字符
     */
    private static boolean check(String str1, String str2) {
        char[] chars1 = str1.toCharArray();
        char[] chars2 = str2.toCharArray();
        Arrays.sort(chars1);
        Arrays.sort(chars2);
        int i = 0, j = 0;
        while (i < str1.length() && j < str2.length()) {
            if (chars1[i] == chars2[j]) return true;
            else if (chars1[i] > chars2[j]) j++;
            else i++;
        }
        return false;
    }

做法挺直接的,如果说字符都限定为小写字母的化,还能进一步优化

200 分题 3:学生方阵

学校组织活动,将学生排成一个矩形方阵。
请在矩形方阵中找到最大的位置相连的男生数量。
这个相连位置在一个直线上,方向可以是水平的,垂直的,成对角线的或者呈反对角线的。
注:学生个数不会超过10000

输入描述:输入的第一行为矩阵的行数和列数,接下来的n行为矩阵元素,元素间用”,”分隔。
输出描述:输出一个整数,表示矩阵中最长的位置相连的男生个数。

示例

输入
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

点击查看代码
public static void main(String[] args) {
        /*
        获取输入
         */
        Scanner in = new Scanner(System.in);
        String[] str = in.nextLine().split(",");
        int m = Integer.parseInt(str[0]);
        int n = Integer.parseInt(str[1]);
        // 构造矩阵
        String[][] matrix = new String[m][n];
        for (int i = 0; i < m; i++) {
            String[] row = in.nextLine().split(",");
            System.arraycopy(row, 0, matrix[i], 0, n);
        }
        // 从左往右,从上往下,对角线和反对角线
        int[][] dp = new int[m][n];
        int[][] dp2 = new int[m][n];
        int[][] dp3 = new int[m][n];
        int[][] dp4 = new int[m][n];
        int ans = 0;
        // 处理只有一行/一列的特例
        if (m == 1) {
            if (matrix[0][0].equals("M")) dp[0][0] = 1;
            for (int j = 1; j < n; j++)
                if (matrix[0][j - 1].equals("M")) {
                    // 如果是连续的长度加一
                    if (matrix[0][j].equals("M")) dp[0][j] = dp[0][j - 1] + 1;
                } else {
                    // 不连续重新确定起点
                    if (matrix[0][j].equals("M")) dp[0][j] = 1;
                }
            for (int j = 0; j < n; j++) ans = Math.max(ans, dp[0][j]);
            System.out.println(ans);
            return;
        }
        if (n == 1) {
            if (matrix[0][0].equals("M")) dp2[0][0] = 1;
            for (int i = 1; i < m; i++) {
                if (matrix[i - 1][0].equals("M")) {
                    if (matrix[i][0].equals("M")) dp2[i][0] = dp2[i - 1][0] + 1;
                } else {
                    if (matrix[i][0].equals("M")) dp2[i][0] = 1;
                }
            }
            for (int i = 0; i < m; i++) ans = Math.max(ans, dp2[i][0]);
            System.out.println(ans);
            return;
        }
        /*
        初始化准备开始动态规划
         */
        for (int i = 0; i < m; i++) {
            // 初始化列
            if (matrix[i][0].equals("M")) {
                dp[i][0] = 1;
                dp2[i][0] = 1;
                dp3[i][0] = 1;
            }
        }
        for (int j = 0; j < n; j++) {
            // 初始化行
            if (matrix[0][j].equals("M")) {
                dp[0][j] = 1;
                dp2[0][j] = 1;
                dp3[0][j] = 1;
                dp4[0][j] = 1;
            }
        }
        // 单独初始化dp4
        for (int i = 0; i < m; i++) if (matrix[i][n - 1].equals("M")) dp4[i][n - 1] = 1;

        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                if (matrix[i][j].equals("M")) {
                    dp[i][j] = dp[i][j - 1] + 1;
                    dp2[i][j] = dp2[i - 1][j] + 1;
                    dp3[i][j] = dp3[i - 1][j - 1] + 1;
                }

            }
        }
        /*
        单独处理反对角线
         */
        for (int i = 1; i < m; i++) {
            for (int j = n - 2; j >= 0; j--) {
                if (matrix[i][j].equals("M")) {
                    if (matrix[i - 1][j + 1].equals("M")) dp4[i][j] = dp4[i - 1][j + 1] + 1;
                }
            }
        }

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                ans = Math.max(ans, Math.max(dp[i][j], Math.max(dp2[i][j], Math.max(dp3[i][j], dp4[i][j]))));
            }
        }
        System.out.println(ans);
    }

dp[i][j] 就代表了从左往右/上往下/对角线/反对角线,第 i 行 / 列 以 j 位置结尾的最大男生连续数量