华为OD-机试
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 位置结尾的最大男生连续数量
本文作者:YaosGHC
本文链接:https://www.cnblogs.com/yaocy/p/17660564.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2022-08-27 链表