夯实算法-判断单词是否能放入填字游戏内

362 阅读2分钟

题目:判断单词是否能放入填字游戏内

给你一个 m x n 的矩阵 board ,它代表一个填字游戏 当前 的状态。填字游戏格子中包含小写英文字母(已填入的单词),表示  格的 ' ' 和表示 障碍 格子的 '#' 。

如果满足以下条件,那么我们可以 水平 (从左到右 或者 从右到左)或 竖直 (从上到下 或者 从下到上)填入一个单词:

  • 该单词不占据任何 '#' 对应的格子。
  • 每个字母对应的格子要么是 ' ' (空格)要么与 board 中已有字母 匹配 。
  • 如果单词是 水平 放置的,那么该单词左边和右边 相邻 格子不能为 ' ' 或小写英文字母。
  • 如果单词是 竖直 放置的,那么该单词上边和下边 相邻 ****格子不能为 ' ' 或小写英文字母。

给你一个字符串 word ,如果 word 可以被放入 board 中,请你返回 true ,否则请返回 false 。

示例 1:

输入: board = [["#", " ", "#"], [" ", " ", "#"], ["#", "c", " "]], word = "abc"
输出: true
解释: 单词 "abc" 可以如上图放置(从上往下)。

示例 2:

输入: board = [[" ", "#", "a"], [" ", "#", "c"], [" ", "#", "a"]], word = "ac"
输出: false
解释: 无法放置单词,因为放置该单词后上方或者下方相邻格会有空格。

示例 3:

输入: board = [["#", " ", "#"], [" ", " ", "#"], ["#", " ", "c"]], word = "ca"
输出: true
解释: 单词 "ca" 可以如上图放置(从右到左)。

 

提示:

  • m == board.length
  • n == board[i].length
  • 1<=mn<=21051 <= m * n <= 2 * 10^5
  • board[i][j] 可能为 ' ' ,'#' 或者一个小写英文字母。
  • 1 <= word.length <= max(m, n)
  • word 只包含小写英文字母。

解题思路

从每个位置开始,如果有任何一个位置能满足以下条件则返回true,如直至所有位置都访问过无法匹配则返回false 条件:位置向上下左右四个方向寻找,单词结尾能在board内,单词每一位的board要么为空格要么相同字符,单词放置-1和length位置要么是超出board范围

补充最外圈的 2 直接根据当前位置水平方向的左右边界或者竖直方向上的上下边界判断是否可以放置 3 校验2 成功后判断字符串是否可以放置

代码实现

public boolean placeWordInCrossword(char[][] board, String word) {
    int n = board.length;
    int m = board[0].length;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            boolean res = helper(board, word, i, j);
            if (res) {
                return true;
            }
        }
    }
    return false;
}

public boolean helper(char[][] board, String word, int r, int c) {
    int n = board.length;
    int m = board[0].length;
    int length = word.length();
    boolean res = false;
    if (board[r][c] != word.charAt(0) && board[r][c] != ' ') {
        return res;
    }
    for (int j = 0; j < 4; j++) {
        int starty = r - pos[j][0]; //开头前一个
        int startx = c - pos[j][1]; //开头前一个
        int endy = r + pos[j][0] * (length - 1); //结尾最后一个
        int endx = c + pos[j][1] * (length - 1); //结尾最后一个
        if (endy < 0 || endy >= n || endx < 0 || endx >= m) {
            continue; //结尾不能放在board中了
        }
        endy = r + pos[j][0] * (length); //结尾后一个
        endx = c + pos[j][1] * (length); //结尾后一个
        if ((startx < 0 || starty < 0 || startx >= m || starty >= n || (startx >= 0 && startx < m && starty >= 0 && starty < n && board[starty][startx] == '#')) &&
            (endx < 0 || endy < 0 || endx >= m || endy >= n || (endx >= 0 && endx < m && endy >= 0 && endy < n && board[endy][endx] == '#'))) { //要么顶头要么顶着#
            if (length > 1) {
                for (int i = 1; i < length; i++) {
                    int y = r + pos[j][0] * i;
                    int x = c + pos[j][1] * i;
                    if ((board[y][x] == word.charAt(i) || board[y][x] == ' ')) {
                        if (i == length - 1) {
                            return true;
                        }
                    } else {
                        break;
                    }
                }
            } else {
                return true;
            }
        }
    }
    return res;
}

运行结果

Snipaste_2023-05-30_22-54-14.png

复杂度分析

  • 空间复杂度:O(1)
  • 时间复杂度:O(n)

掘金(JUEJIN) 一起分享知识, Keep Learning!