全网最全面的华为OD机试真题汇总,100%原题题库,不需要开会员即可查看全部内容,更多考题请查看真题库。
真题库:https://www.yuque.com/codernav.com/od
题目:查找单入口空闲区域
时间限制:1s 空间限制:256MB 限定语言:不限
题目描述:
给定一个 m x n 的矩阵,由若干字符 ‘X’ 和 ‘O’构成,’X’表示该处已被占据,’O’表示该处空闲,请找到最大的单入口空闲区域。
解释:
空闲区域是由连通的’O’组成的区域,位于边界的’O’可以构成入口,单入口空闲区域即有且只有一个位于边界的’O’作为入口的由连通的’O’组成的区域。
如果两个元素在水平或垂直方向相邻,则称它们是“连通”的。
输入描述:
第一行输入为两个数字,第一个数字为行数m,第二个数字列数n,两个数字以空格分隔,1 <= m, n <= 200,
剩余各行为矩阵各行元素,元素为’X’ 或 ‘O’,各元素间以空格分隔。
输出描述:
若有唯一符合要求的最大单入口空闲区域,输出三个数字,第一个数字为入口行坐标(范围为0~行数-1),第二个数字为入口列坐标(范围为0~列数-1),第三个数字为区域大小,三个数字以空格分隔;
若有多个符合要求的最大单入口空闲区域,输出一个数字,代表区域的大小;
若没有,输出NUL。
示例1
输入:
4 4
X X X X
X O O X
X O O X
X O X X
输出:
3 1 5
说明:
存在最大单入口区域,入口行坐标3,列坐标1,区域大小5
示例2
输入:
4 5
X X X X X
O O O O X
X O O O X
X O X X O
输出:
3 4 1
说明:
存在最大单入口区域,入口行坐标3,列坐标4,区域大小1
示例3
输入:
5 4
X X X X
X O O O
X O O O
X O O X
X X X X
输出:
NULL
说明:
不存在最大单入口区域
示例4
输入:
5 4
X X X X
X O O O
X X X X
X O O O
X X X X
输出:
3
说明:
存在两个大小为3的最大单入口区域,两个入口横纵坐标分别为1,3和3,3
解题思路:
通过回溯法求出所有满足的区域,在回溯的同时记录其入口坐标,入口个数大于1则不符合要求;入口个数等于1时,判断其区域大小;如果存在多个区域,且区域大小相同,则只需记录其大小;其他情况则需要记录区域最大值和横纵坐标。
代码实现一:
package com.codernav.demo.hwod.exam; import java.util.ArrayList; import java.util.List; import java.util.Scanner; /** * @title 查找单入口空闲区域 * @Description 给定一个 m x n 的矩阵,由若干字符 'X' 和 'O'构成,'X'表示该处已被占据,'O'表示该处空闲,请找到最大的单入口空闲区域。 * @Author 开发者导航 * @website https://codernav.com * @date 2023/5/13 */ public class Main { public static int m; public static int n; public static String[][] strings; public static int[] rukou = new int[2]; //入口坐标 public static int count = 0; //入口个数 public static void main(String[] args) { Scanner sc = new Scanner(System.in); m = sc.nextInt(); n = sc.nextInt(); strings = new String[m][n]; sc.nextLine(); for (int i = 0; i < m; i++) { String[] strInput = sc.nextLine().split(" "); for (int j = 0; j < n; j++) { strings[i][j] = strInput[j]; } } int max = 0; //最大的区域大小 List<int[]> quyu = new ArrayList<>(); //最大区域的入口坐标和其区域大小的集合 for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (strings[i][j].equals("O")) { strings[i][j] = "X"; //已经统计过的区域置为"X" List<int[]> zuobiao = new ArrayList<>(); //区域中的坐标集合 zuobiao.add(new int[]{i, j}); qiuquyu(i, j, zuobiao); if (count == 1) { //只有一个入口的区域 if (max == zuobiao.size()) { //有大小相同的单入口空闲区域,只需要大小,无需坐标 quyu.clear(); } else if (max < zuobiao.size()) { quyu.clear(); quyu.add(new int[]{rukou[0], rukou[1], zuobiao.size()}); max = zuobiao.size(); } } count = 0; //重置入口数量 rukou = new int[2]; //重置入口坐标 } } } if (quyu.size() == 1) { int[] res = quyu.get(0); System.out.println(res[0] + " " + res[1] + " " + res[2]); } else if (max != 0) { System.out.println(max); } else { System.out.println("NULL"); } } /** * @param x 横坐标 * @param y 纵坐标 * @param list 区域内的坐标集合 */ public static void qiuquyu(int x, int y, List<int[]> list) { if (x == 0 || x == m - 1 || y == 0 || y == n - 1) { //边界为入口坐标 count++; //入口的数量计数 rukou[0] = x; rukou[1] = y; } if (x < m - 1) { if (strings[x + 1][y].equals("O")) { strings[x + 1][y] = "X"; //已经统计过的区域需要置为"X",避免统计重复 list.add(new int[]{x + 1, y}); qiuquyu(x + 1, y, list); } } if (y < n - 1) { if (strings[x][y + 1].equals("O")) { strings[x][y + 1] = "X"; //已经统计过的区域需要置为"X",避免统计重复 list.add(new int[]{x, y + 1}); qiuquyu(x, y + 1, list); } } if (y > 0) { if (strings[x][y - 1].equals("O")) { strings[x][y - 1] = "X"; //已经统计过的区域需要置为"X",避免统计重复 list.add(new int[]{x, y - 1}); qiuquyu(x, y - 1, list); } } } }
代码实现二:
package com.codernav.demo.hwod.exam; import java.util.HashMap; import java.util.Map; import java.util.Scanner; /** * @title 查找单入口空闲区域 * @Description 给定一个 m x n 的矩阵,由若干字符 'X' 和 'O'构成,'X'表示该处已被占据,'O'表示该处空闲,请找到最大的单入口空闲区域。 * @Author 开发者导航 * @website https://codernav.com * @date 2023/5/13 */ public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); while (in.hasNextInt()) {// 注意,如果输入是多个测试用例,请通过while循环处理多个测试用例 int m = in.nextInt(); int n = in.nextInt(); in.nextLine(); Character[][] ca = new Character[m][n]; for (int i = 0; i < m; i++) { String[] sa = in.nextLine().split(" "); for (int j = 0; j < n; j++) { ca[i][j] = sa[j].charAt(0); } } int maxCount = 0; HashMap<String, Integer> map = new HashMap<>(); for (int j = 0; j < n; j++) { if (ca[0][j] == 'O') { int count = calc(copy(ca), 0, j, true); if (count > 0) { String key = 0 + " " + j; map.put(key, count); if (count > maxCount) { maxCount = count; } } } if (ca[m - 1][j] == 'O') { int count2 = calc(copy(ca), m - 1, j, true); if (count2 > 0) { String key = (m - 1) + " " + j; map.put(key, count2); if (count2 > maxCount) { maxCount = count2; } } } } for (int i = 1; i < m - 1; i++) { if (ca[i][0] == 'O') { int count = calc(copy(ca), i, 0, true); if (count > 0) { String key = i + " " + 0; map.put(key, count); if (count > maxCount) { maxCount = count; } } } if (ca[i][n - 1] == 'O') { int count2 = calc(copy(ca), i, n - 1, true); if (count2 > 0) { String key = i + " " + (n - 1); map.put(key, count2); if (count2 > maxCount) { maxCount = count2; } } } } String maxKey = ""; for (Map.Entry<String, Integer> e : map.entrySet()) { if (e.getValue() == maxCount) { if (maxKey.isEmpty()) { maxKey = e.getKey(); } else { maxKey = "more"; break; } } } if (maxCount == 0) { System.out.println("NULL"); } else if (maxKey == "more") { System.out.println(maxCount); } else { System.out.println(maxKey + " " + maxCount); } } } public static Character[][] copy(Character[][] a) { int m = a.length; int n = a[0].length; Character[][] ca = new Character[m][n]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { ca[i][j] = a[i][j]; } } return ca; } public static int calc(Character[][] ca, int i, int j, boolean isRuKou) { if (!isRuKou) { if (i == 0 || i == ca.length - 1 || j == 0 || j == ca[0].length - 1) { return 0; } } ca[i][j] = 'X'; int count = 1; if (j + 1 < ca[0].length && ca[i][j + 1] == 'O') { int count1 = calc(ca, i, j + 1, false); if (count1 == 0) { return 0; } count += count1; } if (i + 1 < ca.length && ca[i + 1][j] == 'O') { int count1 = calc(ca, i + 1, j, false); if (count1 == 0) { return 0; } count += count1; } if (j - 1 >= 0 && ca[i][j - 1] == 'O') { int count1 = calc(ca, i, j - 1, false); if (count1 == 0) { return 0; } count += count1; } if (i - 1 >= 0 && ca[i - 1][j] == 'O') { int count1 = calc(ca, i - 1, j, false); if (count1 == 0) { return 0; } count += count1; } return count; } }