leetcode刷题自记录——剑指offer12/13

175 阅读1分钟

题目12 矩阵中的路径

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

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

例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。

word2.jpg

思路

矩阵里面搜索的题想到用dfs,但是如何记录已经搜索过的字母的?我之前的思路是使用一个visited矩阵来标记每一次搜索中使用过的字母,但是想想好像很复杂。后来看了题解真是豁然开朗,利用dfs+剪枝即可,直接贴代码吧。

代码

官方题解中直接四个dfs还可以优化成使用for循环判断dfs进入条件是否满足,如下所示:

dirt = [-1,0,1,0,-1]
for i in range(4):
    xx = x+dirt[i]
    yy = y+dirt[i+1]
    if xx>=0 and yy>=0 and xx<len(dp) and yy<len(dp[0]):
        res = res or dfs(xx,yy,k+1

官方题解

class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        def dfs(i, j, k):
            if not 0 <= i < len(board) or not 0 <= j < len(board[0]) or board[i][j] != word[k]: return False
            if k == len(word) - 1: return True
            board[i][j] = ''
            res = dfs(i + 1, j, k + 1) or dfs(i - 1, j, k + 1) or dfs(i, j + 1, k + 1) or dfs(i, j - 1, k + 1)
            board[i][j] = word[k]
            return res

        for i in range(len(board)):
            for j in range(len(board[0])):
                if dfs(i, j, 0): return True
        return False

题目13 机器人运动范围

地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?

思路

这题刚开始觉得是动态规划,先判断出哪些格子可以被走到,再将那些上下左右四个方向的格子均为False的True格子给去掉即可。这样做的问题是有些格子它的临近格子其实也不能走到,但是由于还没遍历到它,因此不能使用该方法,如图所示,打叉的格子都是实际上不能被到达的。

格子.jpg

后面观察发现其实只需要从左上角开始进行dfs,类似于得到岛屿的最大面积即可。

代码

class Solution:
    def movingCount(self, m: int, n: int, k: int) -> int:
        #感觉是个动态规划的题
        dp = [[0]*n for _ in range(m)]
        self.count = 0
        #将数字的各位相加
        def sum(x):
            s = str(x)
            res = 0
            for i in range(len(s)):
                res+=int(s[i])
            return res

        dirt = [-1,0,1,0,-1]
        #岛屿面积
        def dfs(x, y, dp):
            if dp[x][y]==0:
                return
            else:
                dp[x][y]=0
                self.count+=1
                for i in range(4):
                    xx = x+dirt[i]
                    yy = y+dirt[i+1]
                    if xx>=0 and yy>=0 and xx<len(dp) and yy<len(dp[0]):
                        dfs(xx,yy,dp)
                        
        for i in range(m):
            for j in range(n):
                if sum(i)+sum(j)<=k:
                    dp[i][j] = 1

        dfs(0,0,dp)

        return self.count