首页 > 其他分享 >力扣-419. 甲板上的战舰

力扣-419. 甲板上的战舰

时间:2024-04-27 10:22:05浏览次数:27  
标签:int 复杂度 力扣 ++ board 战舰 419 row

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))\)

标签:int,复杂度,力扣,++,board,战舰,419,row
From: https://www.cnblogs.com/trmbh12/p/18161794

相关文章

  • 力扣-598. 区间加法 II
    1.题目题目地址(598.区间加法II-力扣(LeetCode))https://leetcode.cn/problems/range-addition-ii/题目描述给你一个mx n的矩阵 M和一个操作数组op。矩阵初始化时所有的单元格都为0。ops[i]=[ai,bi]意味着当所有的0<=x<ai和0<=y<bi时,M[x][y]应......
  • 力扣-LCR 126. 斐波那契数
    1.题目题目地址(LCR126.斐波那契数-力扣(LeetCode))https://leetcode.cn/problems/fei-bo-na-qi-shu-lie-lcof/题目描述斐波那契数(通常用F(n)表示)形成的序列称为斐波那契数列。该数列由0和1开始,后面的每一项数字都是前面两项数字的和。也就是:F(0)=0,F(1)=1F(n......
  • TODO-力扣-707. 设计链表
    1.题目题目地址(707.设计链表-力扣(LeetCode))https://leetcode.cn/problems/design-linked-list/题目描述你可以选择使用单链表或者双链表,设计并实现自己的链表。单链表中的节点应该具备两个属性:val和next。val是当前节点的值,next是指向下一个节点的指针/引用。如果......
  • 力扣-118. 杨辉三角
    1.题目介绍题目地址(118.杨辉三角-力扣(LeetCode))https://leetcode.cn/problems/pascals-triangle/题目描述给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。在「杨辉三角」中,每个数是它左上方和右上方的数的和。 示例1:输入:numRows=5输出:[[1],......
  • 力扣-442. 数组中重复的数据
    1.题目介绍题目地址(442.数组中重复的数据-力扣(LeetCode))https://leetcode.cn/problems/find-all-duplicates-in-an-array/题目描述给你一个长度为n的整数数组nums,其中nums的所有整数都在范围[1,n]内,且每个整数出现一次或两次。请你找出所有出现两次的整数,......
  • 力扣-448. 找到所有数组中消失的数字
    1.题目题目地址(448.找到所有数组中消失的数字-力扣(LeetCode))https://leetcode.cn/problems/find-all-numbers-disappeared-in-an-array/题目描述给你一个含n个整数的数组nums,其中nums[i]在区间[1,n]内。请你找出所有在[1,n]范围内但没有出现在nums中的数字,......
  • 力扣-645. 错误的集合
    1.题目介绍题目地址(645.错误的集合-力扣(LeetCode))https://leetcode.cn/problems/set-mismatch/题目描述集合s包含从1到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合丢失了一个数字并且有一个数字重复。......
  • 力扣-697. 数组的度
    1.题目介绍题目地址(697.数组的度-力扣(LeetCode))https://leetcode.cn/problems/degree-of-an-array/题目描述给定一个非空且只包含非负数的整数数组 nums,数组的度的定义是指数组里任一元素出现频数的最大值。你的任务是在nums中找到与 nums 拥有相同大小的度的最短......
  • 力扣-396. 旋转函数
    1.题目介绍题目地址(396.旋转函数-力扣(LeetCode))https://leetcode.cn/problems/rotate-function/题目描述给定一个长度为n的整数数组 nums 。假设 arrk 是数组 nums 顺时针旋转k个位置后的数组,我们定义 nums 的旋转函数  F 为:F(k)=0*arrk[0]+1*......
  • 力扣-189. 轮转数组
    1.题目题目地址(189.轮转数组-力扣(LeetCode))https://leetcode.cn/problems/rotate-array/题目描述给定一个整数数组nums,将数组中的元素向右轮转k 个位置,其中 k 是非负数。 示例1:输入:nums=[1,2,3,4,5,6,7],k=3输出:[5,6,7,1,2,3,4]解释:向右轮转1步......