当前位置: 首页 > article >正文

Leetcode 79. 单词搜索

在这里插入图片描述

心路历程:

做完这道题才发现是回溯,一开始想的是递归,判断完第i个字符后,只需要挨个判断第i+1个字符在不在第i个字符的邻域。后来发现由于不能重复使用元素,所以需要维护一个visited列表,并且在遍历所有可能组合的时候还得撤回之前的选择。
回过头来从回溯的角度思考这个问题:每个边(路径)可以看作是选择哪个字母,候选集合就是当前邻域(结点)。相当于‘选哪个’的问题。

注意的点:

1、题目中要求字符不能重复选择,因此需要维护一个visited,并且需要在遍历结束后撤销选择。
2、debug时可以打印每个结点的值来看递归函数执行的正确性。

解法: 回溯

因为一开始以为是DP问题,所以为了后面用cache装饰器方便而参数化了递归函数的输入,写完后发现其实代码可以简化,可以把首字母的可选邻域看作整个board。

class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        # 递归

        # 获取第一个单词的所有可能位置和其邻域
        first = word[0]
        pos_first = []
        m = len(board)
        n = len(board[0])
        for i_ in range(m):
            for j_ in range(n):
                if board[i_][j_] == first:
                    pos_first.append((i_, j_))
        if not pos_first:
            return False
        visited = []
        # print(pos_first)
        # @cache 回溯不能cache
        def dfs(i, j, k):  # 上一个字母的位置是i,j; 此时判断第k个字母在不在其i,j的邻域中
            assert k > 0
            if k == len(word):
                return True
            nonlocal m, n, board
            # 先求i,j的邻域
            linyu = []
            if i + 1 <= m - 1:
                linyu.append([i+1, j])
            if i - 1 >= 0:
                linyu.append([i-1, j])
            if j + 1 <= n - 1:
                linyu.append([i, j+1])
            if j - 1 >= 0:
                linyu.append([i, j-1])
            flag = False
            for eve in linyu:
                if board[eve[0]][eve[1]] == word[k] and (eve[0], eve[1]) not in visited:
                    visited.append((eve[0], eve[1]))
                    flag = flag or dfs(eve[0], eve[1], k+1)
                    visited.pop()
            # print(i,j,k,flag, linyu, visited)
            return flag

        res = False
        for each_init in pos_first:
            visited.append((each_init[0], each_init[1])) # 因为不能重复选择字母
            res = res or dfs(each_init[0], each_init[1], 1)
            visited.pop()

        return res

http://www.kler.cn/a/274430.html

相关文章:

  • 在Java虚拟机(JVM)中,方法可以分为虚方法和非虚方法。
  • 设计模式12:状态模式
  • 智能工厂的设计软件 三种处理单元(NPU/GPU/CPU)及其在深度学习框架中的作用 之4(百度文库答问 之2)
  • PostgreSQL技术内幕21:SysLogger日志收集器的工作原理
  • 使用React构建一个掷骰子的小游戏
  • Pytest-Bdd-Playwright 系列教程(17):标签管理(Tags)
  • 【进阶五】Python实现SDVRP(需求拆分)常见求解算法——自适应大邻域算法(ALNS)
  • 学习vue3第六节(vue3 中 computed watch watchEffect)
  • 有什么小程序适合个人开发?
  • Aigtek超声功率放大器产品介绍
  • 力扣1. 两数之和
  • 腾讯云服务器多少钱1个月?2024一个月收费阿济格IE吧
  • 数据结构:详解【顺序表】的实现
  • PlantUML Integration 编写短信服务类图
  • 深入挖掘C语言之——枚举
  • Redis数据结构对象中的对象共享、对象的空转时长
  • 【Godot4.2】2D导航01 - AStar2D及其使用方法
  • python企业编码管理的程序(附源码)
  • 微信小程序接口请求出错:request:fail url not in domain list:xxxxx
  • 代码随想录算法训练营第53天 | 1143.最长公共子序列 ,1035.不相交的线 ,53. 最大子序和
  • 5.1.4、【AI技术新纪元:Spring AI解码】Amazon Bedrock
  • ASP .Net Core ILogger日志服务
  • MongoDB聚合运算符:$getField
  • 点云配准9:Colored-ICP的Open3D实现
  • Echarts折线图x轴不显示全部数据的解决办法,亲测有效
  • 电脑数据安全新利器:自动备份文件的重要性与实用方案