力扣-419. 甲板上的战舰

1.题目

题目地址(419. 甲板上的战舰 - 力扣(LeetCode))

https://leetcode.cn/problems/battleships-in-a-board/

题目描述

给你一个大小为 m x n 的矩阵 board 表示甲板,其中,每个单元格可以是一艘战舰 'X' 或者是一个空位 '.' ,返回在甲板 board 上放置的 战舰 的数量。

战舰 只能水平或者垂直放置在 board 上。换句话说,战舰只能按 1 x k1 行,k 列)或 k x 1k 行,1 列)的形状建造,其中 k 可以是任意大小。两艘战舰之间至少有一个水平或垂直的空位分隔 (即没有相邻的战舰)。

 

示例 1:

输入:board = [["X",".",".","X"],[".",".",".","X"],[".",".",".","X"]]
输出:2

示例 2:

输入:board = [["."]]
输出:0

 

提示:

  • m == board.length
  • n == board[i].length
  • 1 <= m, n <= 200
  • board[i][j]'.''X'

 

进阶:你可以实现一次扫描算法,并只使用 O(1) 额外空间,并且不修改 board 的值来解决这个问题吗?

2.题解

2.1 遍历扫描(枚举-标记)

思路

由于已知战舰必然是在一行或者一列上, 且相邻两艘必定隔开一个空格, 我们找到一个X时,
就可以顺着row或者col往后进行遍历, 将所有相邻的X均变为'.'(进行标记),代表是一艘战舰, 这样之后就不会重复寻找了.

两种思路,没有本质区别
1.允许扫描多次,但空间只能 O(1):每次遇到 X 的格子,则将 X 所在的战舰修改为 .,统计完答案后,再扫描一次,将 . 恢复为 X 即可;
2.扫描一次,但空间允许 O(m∗n):使用一个与矩阵同等大小的辅助数组 vis 记录访问过的位置即可

代码

  • 语言支持:C++

C++ Code:


class Solution {
public:
    int countBattleships(vector<vector<char>>& board) {
        int row = board.size(), col = board[0].size();
        int ans = 0;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (board[i][j] == 'X') {
                    for (int k = i + 1; k < row && board[k][j] == 'X'; k++) {
                        board[k][j] = '.';
                    }
                    for (int k = j + 1; k < col && board[i][k] == 'X'; k++) {
                        board[i][k] = '.';
                    }
                    ans++;
                }
            }
        }
        return ans;
    }
};

复杂度分析

令 n 为数组长度。

  • 时间复杂度:O(m×n×max(m,n))
  • 空间复杂度:O(1))

2.2 去重判断

思路

思考上述两种做法,我们本质 都是在战舰的首个格子进行计数,并将该战舰的所有格子进行处理,同时使用去重手段(原数组标记 或 使用辅助数组)来防止该战舰在后面遍历中被重复计数。
如果我们能够找到某种规律,直接判断出某个 X 格子是否为战舰开头,则不再需要其他去重手段。

我们对于一个战舰开头, 其左方和上方必然不可能是'X', 如果是则不为战舰开头(注意位于i == 0 和 j == 0 的特殊情况, 这是没有左方和上方的, 判断一下即可)

代码

class Solution {
public:
    int countBattleships(vector<vector<char>>& board) {
        int row = board.size(), col = board[0].size();
        int ans = 0;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if(i > 0 && board[i-1][j] == 'X') continue;
                if(j > 0 && board[i][j-1] == 'X') continue;
                if(board[i][j] == 'X') ans++;
            }
        }
        return ans;
    }
};

复杂度分析

令 n 为数组长度。

  • 时间复杂度:O(m×n)
  • 空间复杂度:O(1))
posted @   DawnTraveler  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示