华为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 位置结尾的最大男生连续数量