刷题记录 HOT100回溯算法-6:79. 单词搜索

题目:79. 单词搜索

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例 1:

复制代码
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

示例 2:

复制代码
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE"
输出:true

示例 3:

复制代码
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB"
输出:false

提示:

  • m == board.length
  • n = board[i].length
  • 1 <= m, n <= 6
  • 1 <= word.length <= 15
  • board 和 word 仅由大小写英文字母组成

一、模式识别

1.棋盘格:回溯法

棋盘格问题,回溯法典型应用,用回溯算法

层间:word内顺序访问

层内:board遍历或上一个字母上下左右

无需找到所有结果,找到第一个结果后返回

2.搜索方式

1.word首字母在board中二维遍历

2.word内(层间)顺序访问,剩余字母分别搜索上一个字母的上下左右

3.访问过的字母不可以重复访问

二.代码实现

1.基础实现

python 复制代码
class Solution:
    def get_candidate(self, board, visited, i, j):
        candidate = []
        if i - 1 >= 0 and not visited[i - 1][j]:
            candidate.append((board[i - 1][j], i - 1, j))
        if j - 1 >= 0 and not visited[i][j - 1]:
            candidate.append((board[i][j - 1], i, j - 1))
        if i + 1 < len(board) and not visited[i + 1][j]:
            candidate.append((board[i + 1][j], i + 1, j))
        if j + 1 < len(board[0]) and not visited[i][j + 1]:
            candidate.append((board[i][j + 1], i, j + 1))
        return candidate

    def backtracking(self, board, word, visited, start_idx, i, j):
        if start_idx == len(word):
            return True
        if start_idx == 0:
            for i in range(len(board)):
                for j in range(len(board[i])):
                    if board[i][j] == word[0]:
                        visited[i][j] = True
                        if self.backtracking(board, word, visited, 1, i, j):
                            return True
                        visited[i][j] = False
        else:
            for ch, a, b in self.get_candidate(board, visited, i, j):
                if ch == word[start_idx]:
                    visited[a][b] = True
                    if self.backtracking(board, word, visited, start_idx + 1, a, b):
                        return True
                    visited[a][b] = False
        return False
        
    def exist(self, board: List[List[str]], word: str) -> bool:
        visited = [[False] * len(board[0]) for _ in range(len(board))]
        return self.backtracking(board, word, visited, 0, -1, -1)

start_idx记录访问顺序

visited用于标记访问过的字母

首字母二维遍历board

剩余字母层间顺序访问,层内访问上一个字母在board中的上下左右

耗时:2000ms-4000ms

2.启发式搜索

python 复制代码
class Solution:
    def get_candidate(self, board, i, j):
        candidate = []
        if i - 1 >= 0 and board[i - 1][j]:
            candidate.append((board[i - 1][j], i - 1, j))
        if j - 1 >= 0 and board[i][j - 1]:
            candidate.append((board[i][j - 1], i, j - 1))
        if i + 1 < len(board) and board[i + 1][j]:
            candidate.append((board[i + 1][j], i + 1, j))
        if j + 1 < len(board[0]) and board[i][j + 1]:
            candidate.append((board[i][j + 1], i, j + 1))
        return candidate

    def backtracking(self, board, word, start_idx, i, j):
        if start_idx == len(word):
            return True
        if start_idx == 0:
            for i in range(len(board)):
                for j in range(len(board[i])):
                    if board[i][j] == word[0]:
                        board[i][j] = False
                        if self.backtracking(board, word, 1, i, j):
                            return True
                        board[i][j] = word[0]
        else:
            for ch, a, b in self.get_candidate(board, i, j):
                if ch == word[start_idx]:
                    board[a][b] = False
                    if self.backtracking(board, word, start_idx + 1, a, b):
                        return True
                    board[a][b] = word[start_idx]
        return False
        
    def exist(self, board: List[List[str]], word: str) -> bool:
        # visited = [[False] * len(board[0]) for _ in range(len(board))]
        cnt=Counter(c for row in board for c in row)
        if not cnt>=Counter(word):
            return False
        if cnt[word[-1]]<cnt[word[0]]:
            word=word[::-1]
        return self.backtracking(board, word, 0, -1, -1)

在提交排行榜中看到的启发式搜索

思路:主要搜索开销都在第一步的board的遍历,于是从第一步开刀

实现逻辑:如果尾端字母在board出现频率低于首端则word反序

计算开销直接降到0ms-3ms

相关推荐
职豚求职小程序1 小时前
易方达基金27秋招笔试|场次+考情全梳理
笔记
张张123y3 小时前
后端第十四课:Agent 记忆系统(让 Agent 记住上下文和用户,跨会话不健忘)
java·大数据·人工智能·python·agent·记忆
happylifetree8 小时前
Python67:核心语法-函数进阶-参数类型(函数作为参数)
python
小羊没烦恼!8 小时前
铁道部新客票系统设计(二)
开发语言·前端·数据库·python·oracle·c#·php
quantdash_cc9 小时前
从实时行情到价格观察表:用 Python 和 Pandas 构建策略输入数据
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
镜子AI9 小时前
镜子AI工程实践:用 Python 做 GEO 实体一致性审计,并自动生成 JSON-LD 结构化数据
人工智能·python·json
罗湖老棍子10 小时前
【例 1】Sightseeing Trip(信息学奥赛一本通- P1494)(洛谷-P10927)
数据结构·算法·图论·最短路·floyd·最小环
文丑颜不良啊10 小时前
LeetCode201~225题目解析
java·leetcode
stsdddd12 小时前
YOLO算法建筑工地安全帽目标检测数据集16881张:标注核对笔记
算法·yolo·目标检测
CV爱数码13 小时前
论文精读|Learned Primal-Dual:把原始–对偶算法展开成网络
图像处理·算法·计算机视觉·ct·重建·断层扫描