前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【面试高频题】难度 1/5,简单「脑筋急转弯」模拟题

【面试高频题】难度 1/5,简单「脑筋急转弯」模拟题

作者头像
宫水三叶的刷题日记
发布2022-04-06 21:47:12
6820
发布2022-04-06 21:47:12
举报
文章被收录于专栏:宫水三叶的刷题日记

题目描述

这是 LeetCode 上的「419. 甲板上的战舰」,难度为「中等」

Tag : 「脑筋急转弯」

给你一个大小为

的矩阵

表示甲板,其中,每个单元格可以是一艘战舰 'X' 或者是一个空位 '.' ,返回在甲板

上放置的 战舰 的数量。

战舰 只能水平或者垂直放置在

上。换句话说,战舰只能按

1行,k 列)或

k行,1 列)的形状建造,其中 k可以是任意大小。

两艘战舰之间至少有一个水平或垂直的空位分隔 (即没有相邻的战舰)。

示例 1:

代码语言:javascript
复制
输入:board = [["X",".",".","X"],[".",".",".","X"],[".",".",".","X"]]

输出:2

示例 2:

代码语言:javascript
复制
输入:board = [["."]]

输出:0

提示:

进阶:你可以实现一次扫描算法,并只使用

额外空间,并且不修改 board 的值来解决这个问题吗?

脑筋急转弯

如果「允许扫描多次」或者「使用与输入同规模的空间」的话,做法都十分简单:

  • 允许扫描多次,但空间只能 :每次遇到 X 的格子,则将 X 所在的战舰修改为 -,统计完答案后,再扫描一次,将 - 恢复为 X 即可;
  • 扫描一次,但空间允许

:使用一个与矩阵同等大小的辅助数组

记录访问过的位置即可。

但题目要求「扫描一次」并且「空间

」,这就需要有点「脑筋急转弯」了。

❝注意这里的「扫描一次」是指使用一次遍历,而非要求每个单元格仅能访问一次,注意两者区别。 ❞

思考上述两种做法,我们本质 都是在战舰的首个格子进行计数,并将该战舰的所有格子进行处理,同时使用去重手段(原数组标记 或 使用辅助数组)来防止该战舰在后面遍历中被重复计数。

如果我们能够找到某种规律,直接判断出某个 X 格子是否为战舰开头,则不再需要其他去重手段。

当且仅当某个 X 格子的「上方」&「左方」不为 X 时,该格子为战舰首个格子,可以进行计数,同时需要注意当前当为 0(没有「上方」)和当前列为 0(没有「左方」)时的边界情况。

  • 一次扫描 +

代码:

代码语言:javascript
复制
class Solution {
    public int countBattleships(char[][] board) {
        int m = board.length, n = board[0].length;
        int ans = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; 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;
    }
}
  • 两次扫描 +

代码:

代码语言:javascript
复制
class Solution {
    public int countBattleships(char[][] board) {
        int m = board.length, n = board[0].length;
        int ans = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (board[i][j] != 'X') continue;
                board[i][j] = '-';
                for (int k = i + 1; k < m && board[k][j] == 'X'; k++) board[k][j] = '-';
                for (int k = j + 1; k < n && board[i][k] == 'X'; k++) board[i][k] = '-';
                ans++;
            }
        }
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (board[i][j] == '-') board[i][j] = 'X';
            }
        }
        return ans;
    }
}
  • 一次扫描 +

代码:

代码语言:javascript
复制
class Solution {
    public int countBattleships(char[][] board) {
        int m = board.length, n = board[0].length;
        int ans = 0;
        boolean[][] vis = new boolean[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (board[i][j] != 'X' || vis[i][j]) continue;
                vis[i][j] = true;
                for (int k = i + 1; k < m && board[k][j] == 'X'; k++) vis[k][j] = true;
                for (int k = j + 1; k < n && board[i][k] == 'X'; k++) vis[i][k] = true;
                ans++;
            }
        }
        return ans;
    }
}

最后

这是我们「刷穿 LeetCode」系列文章的第 No.419 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode。

在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-03-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 宫水三叶的刷题日记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目描述
  • 脑筋急转弯
  • 最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档