news 2026/10/26 18:30:03

矩阵遍历与战舰计数算法解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
矩阵遍历与战舰计数算法解析

1. 问题背景与题目解析

"甲板上的战舰"这个题目乍看有些抽象,实际上它源自一道经典的算法编程题。题目描述通常是:给定一个二维的甲板(矩阵),上面用'X'和'.'标记了战舰的位置和空白区域。战舰只能水平或垂直放置,且不会相邻(即没有两艘战舰在水平或垂直方向上相邻)。要求统计甲板上战舰的数量。

这个题目看似简单,但考察了以下几个核心能力:

  • 对二维矩阵的遍历和理解
  • 对相邻元素关系的判断
  • 对边界条件的处理
  • 对问题本质的抽象能力

2. 战舰识别的基本思路

2.1 直观解法分析

最直观的解法是遍历整个矩阵,每当遇到一个'X'时,就检查它的上方和左方是否也是'X'。如果不是,则认为这是一个新的战舰的头部,计数器加一。

这种方法的正确性基于题目给出的两个关键约束:

  1. 战舰只能是1xN或Nx1的形状(即水平或垂直)
  2. 战舰之间不会相邻

2.2 代码实现示例

def countBattleships(board): count = 0 for i in range(len(board)): for j in range(len(board[0])): if board[i][j] == 'X': # 检查上方和左方是否也是'X' if (i == 0 or board[i-1][j] != 'X') and (j == 0 or board[i][j-1] != 'X'): count += 1 return count

这个解法的时间复杂度是O(mn),其中m和n分别是矩阵的行数和列数,空间复杂度是O(1),因为只使用了常数个额外空间。

3. 算法优化与边界条件

3.1 为什么不需要检查所有四个方向

很多初学者会疑惑为什么只需要检查上方和左方,而不需要检查下方和右方。这是因为:

  • 如果当前'X'是一个战舰的中间部分,那么它的上方或左方必然已经有一个'X'
  • 题目保证战舰不会相邻,所以不需要担心其他战舰的影响
  • 从左上到右下的遍历顺序确保了每个战舰只会被计数一次

3.2 边界条件处理

需要特别注意矩阵边界的情况:

  • 当i=0时,不需要检查上方
  • 当j=0时,不需要检查左方
  • 空矩阵的情况(虽然题目通常保证非空)

4. 实际应用场景

4.1 游戏开发中的应用

这个算法虽然简单,但在游戏开发中有实际应用价值。例如:

  • 战舰类游戏的自动布局验证
  • 游戏存档的状态统计
  • AI对手的局势分析

4.2 图像处理中的连通区域计数

类似的算法可以应用于图像处理中的连通区域计数,只需将'X'视为目标像素,'.'视为背景。虽然实际图像处理需要考虑8连通而不仅仅是4连通,但核心思路是相通的。

5. 常见错误与调试技巧

5.1 初学者容易犯的错误

  1. 双重计数:没有正确处理战舰的连续性,导致同一艘战舰被多次计数
  2. 边界越界:在检查相邻元素时没有考虑矩阵边界
  3. 修改原矩阵:有些解法会修改原矩阵来标记已访问的位置,这在某些场景下可能不被允许

5.2 调试建议

对于这类矩阵遍历问题,建议:

  1. 先用小例子手工模拟算法过程
  2. 打印中间结果验证逻辑
  3. 特别注意边界情况(如全'X'、全'.'、单行、单列等)

6. 算法扩展与变种

6.1 允许战舰相邻的情况

如果去掉"战舰不相邻"的限制,问题会变得复杂很多。这时需要:

  1. 使用DFS或BFS来标记已访问的位置
  2. 需要额外的空间来记录访问状态
  3. 时间复杂度可能提高到O(mn)但空间复杂度变为O(mn)

6.2 三维战舰识别

如果将问题扩展到三维空间(比如立体战舰游戏),算法需要:

  1. 增加z轴方向的检查
  2. 考虑三维连通性
  3. 使用三维数组来表示空间

7. 性能优化实践

对于非常大的矩阵,可以考虑以下优化:

  1. 并行处理:将矩阵分块,在多核或GPU上并行计算
  2. 增量更新:如果矩阵是动态变化的,可以只重新计算受影响区域
  3. 压缩存储:对于稀疏矩阵,使用特殊数据结构节省空间

8. 个人实战经验分享

在实际编程比赛中,这类题目看似简单但很容易因为粗心失分。我的经验是:

  1. 一定要先明确题目给出的所有约束条件
  2. 写代码前先用几个小例子验证思路
  3. 特别注意循环的边界条件
  4. 变量命名要清晰(比如用rows和cols而不是m和n)
  5. 添加适当的注释说明关键逻辑

提示:在面试中遇到这类题目时,建议先和面试官确认所有假设条件,比如战舰的形状限制、相邻规则等。清晰的沟通有时比完美的代码更重要。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/26 18:30:01

海康威视Python移动侦测实战:SDK与ISAPI选型、报警回调与参数调优

简介:这份资源面向已具备一定 Python 基础、希望基于海康威视 SDK 做二次开发并实现移动侦测事件回调的开发者,对应博客中「直接使用」一节的可运行代码整理,解决从零搭建 SDK 调用环境、理清登录与报警回调流程的问题。压缩包共 15 个文件&a…

作者头像 李华
网站建设 2026/10/26 18:28:26

SolidWorks二次开发:参数化建模、工程图自动化与批量出图避坑

简介:这是一份面向 SolidWorks 二次开发入门与进阶者的参数化建模实战工程包,重点解决在 VC 环境下调用 SolidWorks API、组织零件与对话框模块并生成可注册插件等问题。压缩包共 95 个文件,约 4.33MB,包含 16 个 .h、13 个 .cpp …

作者头像 李华
网站建设 2026/10/26 18:27:44

Lodop打印控件实战:从本地服务到模板参数化与避坑指南

简介:这份资源面向需要在网页或桌面程序中实现打印功能的开发者,提供 Lodop 6.0 打印控件的安装包与配套示例集合,可用于快速验证票据、报表、标签等场景下的打印调用方式。压缩包共 43 个文件,约 1.55MB,以 40 个 htm…

作者头像 李华
网站建设 2026/10/26 18:27:43

C#扫码枪开发:USB HID与串口双模稳定接入实战

简介:本资源是一套完整的C#扫码枪通信实战项目,面向Windows桌面应用开发者及.NET初学者,解决USB与串口两种主流接口下条码数据实时捕获与解析的技术难点。项目包含29个文件,涵盖12个核心C#源码(如BarCodeHooK.cs实现系…

作者头像 李华
网站建设 2026/10/26 18:26:29

纯C++手写CNN:im2col卷积与反向传播工程实现

简介:面向希望用 C 理解卷积神经网络底层实现的学习者,这份“卷积神经网络简单实现(C)”提供了一套可编译运行的轻量级 CNN 基础框架。项目在 Ubuntu 16.04 下开发,借助 Eigen3 完成矩阵与向量运算,围绕卷积…

作者头像 李华
网站建设 2026/10/26 18:24:05

Python热度降5%?真正机会在这儿

前几天刷到一个榜单截图,说 Python 在 2026 年的搜索热度比去年同期掉了 5%。评论区一片“Python 要凉了”“学 Python 白学了”的声音。说实话,我第一反应不是焦虑,而是有点想笑——因为我自己这两年接的私活、帮朋友搭的小工具,…

作者头像 李华