华为OD机试_2025_查找单入口空闲区域(Python,100分)(附详细解题思路)

题目描述

给定一个 m x n 的矩阵,由若干字符 'X' 和 'O'构成,'X'表示该处已被占据,'O'表示该处空闲,请找到最大的单入口空闲区域。

解释:

空闲区域是由连通的'O'组成的区域,位于边界的'O'可以构成入口,

单入口空闲区域即有且只有一个位于边界的'O'作为入口的由连通的'O'组成的区域。

如果两个元素在水平或垂直方向相邻,则称它们是"连通"的。

输入描述

第一行输入为两个数字,第一个数字为行数m,第二个数字为列数n,两个数字以空格分隔,1<=m,n<=200。

剩余各行为矩阵各行元素,元素为'X'或'O',各元素间以空格分隔。

输出描述

若有唯一符合要求的最大单入口空闲区域,输出三个数字

第一个数字为入口行坐标(0~m-1)

第二个数字为入口列坐标(0~n-1)

第三个数字为区域大小

三个数字以空格分隔;

若有多个符合要求,则输出区域大小最大的,若多个符合要求的单入口区域的区域大小相同,则此时只需要输出区域大小,不需要输出入口坐标。

若没有,输出NULL。

用例

|----|-------------------------------------|
| 输入 | 4 4 X X X X X O O X X O O X X O X X |
| 输出 | 3 1 5 |
| 说明 | 存在最大单入口区域,入口坐标(3,1),区域大小5 |

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

|----|---------------------------------------------|
| 输入 | 5 4 X X X X X O O O X O O O X O O X X X X X |
| 输出 | NULL |
| 说明 | 不存在最大单入口区域 |

|----|---------------------------------------------|
| 输入 | 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. 空闲区域由连续的'O'构成
  2. 单入口区域要求有且只有一个位于边界的'O'(矩阵边缘)
  3. 输出要求:
  • 唯一最大区域:输出入口坐标和区域大小
  • 多个相同大小的最大区域:只输出区域大小
  • 没有满足条件的区域:输出"NULL"

关键策略

  1. 连通区域检测:使用BFS/DFS遍历所有相邻的'O'
  2. 边界点统计:在遍历时标记位于边界的'O'
  3. 单入口判断:区域只有一个边界点才是单入口区域
  4. 结果筛选:找出最大区域,处理多个相同大小的情况

算法流程

复制代码
1. 遍历矩阵中的每个'O'点
2. 对未访问的'O'进行BFS/DFS:
- 统计区域大小
- 记录所有边界点坐标
3. 判断边界点数量是否为1:
- 是:记录(区域大小, 边界点坐标)
4. 结果处理:
- 没有单入口区域:输出"NULL"
- 唯一最大区域:输出入口坐标和大小
- 多个相同大小区域:输出区域大小
二、完整代码实现
python 复制代码
from collections import deque

def main():
import sys
data = sys.stdin.read().splitlines()
m, n = map(int, data[0].split())
matrix = []
for i in range(1, 1 + m):
matrix.append(data[i].split())

visited = [[False] * n for _ in range(m)]
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
regions = []# 存储单入口区域信息:(size, entrance_x, entrance_y)

for i in range(m):
for j in range(n):
if matrix[i][j] == 'O' and not visited[i][j]:
queue = deque([(i, j)])
visited[i][j] = True
size = 0
boundary_points = []

while queue:
x, y = queue.popleft()
size += 1
# 检查是否为边界点
if x == 0 or x == m - 1 or y == 0 or y == n - 1:
boundary_points.append((x, y))

for dx, dy in directions:
nx, ny = x + dx, y + dy
if 0 <= nx < m and 0 <= ny < n and not visited[nx][ny] and matrix[nx][ny] == 'O':
visited[nx][ny] = True
queue.append((nx, ny))

# 如果是单入口区域
if len(boundary_points) == 1:
x0, y0 = boundary_points[0]
regions.append((size, x0, y0))

# 处理结果
if not regions:
print("NULL")
else:
# 按区域大小降序排序
regions.sort(key=lambda x: x[0], reverse=True)
max_size = regions[0][0]
max_regions = [r for r in regions if r[0] == max_size]

if len(max_regions) > 1:
print(max_size)
else:
size, x, y = max_regions[0]
print(f"{x} {y} {size}")

if __name__ == "__main__":
main()
三、示例解析

示例1:输入

复制代码
4 4
X X X X
X O O X
X O O X
X O X X

执行过程

  1. 检测到区域:包含5个'O'(坐标(1,1),(1,2),(2,1),(2,2),(3,1))
  2. 边界点:(3,1)(唯一)
  3. 记录:(size=5, x=3, y=1)
  4. 输出:3 1 5

图解

复制代码
(0,0) (0,1) (0,2) (0,3)XXXX
(1,0) (1,1) (1,2) (1,3)XOOX
(2,0) (2,1) (2,2) (2,3)XOOX
(3,0) (3,1) (3,2) (3,3)XOXX
边界点↑(红色)

示例2:输入

复制代码
4 5
X X X X X
O O O O X
X O O O X
X O X X O

执行过程

  1. 区域1(左下):7个'O',但有两个边界点(1,0)和(3,1) → 非单入口
  2. 区域2(右下):1个'O',边界点(3,4)(唯一)
  3. 记录:(size=1, x=3, y=4)
  4. 输出: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

执行过程

  1. 检测到两个分离区域:
  • 区域1(第1行):3个'O',边界点(1,3)
  • 区域2(第3行):3个'O',边界点(3,3)
  1. 两个区域大小相同且都是单入口
  2. 输出:3
四、总结

关键要点

  • 边界点判断:检查坐标是否在矩阵边缘
  • 单入口条件:区域必须有且只有一个边界点
  • 结果筛选逻辑
  • 唯一最大区域 → 输出坐标和大小
  • 多个相同大小 → 输出大小
  • 无满足条件 → 输出"NULL"

注意事项

  1. 使用BFS/DFS遍历时注意边界检查
  2. 访问标记避免重复计算
  3. 区域大小比较使用降序排序
  4. 多个相同大小区域只输出大小值

此解法通过系统的区域检测和结果筛选,准确高效地解决了最大单入口空闲区域查找问题,完美符合题目要求。

相关推荐
Jerry1 小时前
LeetCode 28. 找出字符串中第一个匹配项的下标
算法
Jerry3 小时前
LeetCode 459. 重复的子字符串
算法
海石5 小时前
1500分的题目,确实有实力,不过还是我略胜一筹
算法·leetcode
海石5 小时前
【记忆化搜索】条条大路通AC,走好适合你的那一条,走到后再考虑走得快
算法·leetcode
hhzz6 小时前
Python大数据实战(十六):音乐推荐系统——基于协同过滤算法构建个性化歌单引擎
大数据·人工智能·python·数据挖掘·数据分析
SunnyDays10117 小时前
Python PDF 转 Markdown 详解(转换整个文档,特定页面,表格,扫描 PDF)
python·pdf 转 markdown·pdf 转 md·扫描 pdf 转 md·pdf 表格转 md
2601_954706497 小时前
云手机 API 自动化实战:Python 批量控机、挂机脚本完整实现
python·智能手机·自动化
Jerry7 小时前
LeetCode 151. 反转字符串中的单词
算法
a11177610 小时前
LM 算法迭代过程动画演示(SLAM)
算法
头茬韭菜10 小时前
Context 的生死抉择:四层压缩、截断算法与 Session Memory
算法·ai