Leetcode 79. Word Search (词搜索)

原题

Given a 2D board and a word, find if the word exists in the grid.

The word can be constructed from letters of sequentially adjacent cell, where “adjacent” cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.

Example:

board =
[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]

Given word = "ABCCED", return true.
Given word = "SEE", return true.
Given word = "ABCB", return false.

Reference Answer

思路分析

还是经典的回溯法问题。这个题的回溯的起点可以是二维数组的任意位置。

回溯法的判定条件比较简单,需要注意的是把已经走过的路给改变了,不能再走了。python中通过swapcase()交换该字母的大小写即可行。

My Code(有bug,本机跑结果与提交结果不同)

class Solution:
    def exist(self, board, word):
        """
        :type board: List[List[str]]
        :type word: str
        :rtype: bool
        """
        if not board and word:
            return False
        elif board and not word:
            return True
        elif not board and not word:
            return True
        # rows, cols = len(board), len(board[0])
        mark = []
        for x in range(len(board)):
            for y in range(len(board[0])):
                if self.helper(x, y, 0, board, word, mark):
                    return True
        return False

    def helper(self, row, col, word_index, board, word, mark):
        if word_index == len(word):
            return True
        if row < 0 or row >= len(board) or col < 0 or col >= len(board[0]):
            return False
        if board[row][col] != word[word_index]:
            return False
        if board[row][col] in mark:
            return False
        return self.helper(row + 1, col, word_index + 1, board, word, mark + [[row, col]]) or \
               self.helper(row - 1, col, word_index + 1, board, word, mark + [[row, col]]) or \
               self.helper(row, col + 1, word_index + 1, board, word, mark + [[row, col]]) or \
               self.helper(row, col - 1, word_index + 1, board, word, mark + [[row, col]])
  

Reference Code

class Solution(object):
    def exist(self, board, word):
        """
        :type board: List[List[str]]
        :type word: str
        :rtype: bool
        """
        for y in xrange(len(board)):
            for x in xrange(len(board[0])):
                if self.exit(board, word, x, y, 0):
                    return True
        return False

    def exit(self, board, word, x, y, i):
        if i == len(word):
            return True
        if x < 0 or x >= len(board[0]) or y < 0 or y >= len(board):
            return False
        if board[y][x] != word[i]:
            return False
        board[y][x] = board[y][x].swapcase()
        isexit =  self.exit(board, word, x + 1, y, i + 1) or self.exit(board, word, x, y + 1, i + 1) or self.exit(board, word, x - 1, y, i + 1) or self.exit(board, word, x, y - 1, i + 1)
        board[y][x] = board[y][x].swapcase()
        return isexit
  

Note:

  • 这道题花费了大量的时间精力,其中出现的错误有三点:
  1. 对走过的坐标点进行mark的标记方式不对,本来想利用回溯法的优势,直接在return中完成走过点坐标位置的添加,事实上添加方式不对:

    错误方式:mark + [col, row],事实证明这种编程方式的结果为[row_1,col_1,row_2,col_2...],不是想要的[[row_1, col_2], [row_2, col_2]...],因此,在这种方式下,想通过if board[row][col] in mark:来判断是否已经走过该坐标点,本身就不证明,这种判断方式永远不成立(如 [1,2] not in [1,2,3,4]恒成立);
    若想通过该方式进行判定,需要用mark + [[col, row]],这样,标记的坐标点为[[row_1, col_1], [row_2, col_2]. [row_3, col_3]...],就可以进行if board[row][col] in mark:来判断是否已经走过该坐标点了。

  2. 错误地进行了开始以为应该是用if word_index == len(word)-1:来作为判定成功的标志,事实上,应该是用if word_index == len(word):,因为该判定语句是放在第一个判定条件的(事实证明,该成功判定条件必须放在首位置,详见第3条),此时,还没有进行索引指定内容的判别,如 if board[row][col] != word[word_index]等,因此,成立条件是在判定完所有0:len(word)-1所有内容后,此时word_index == len(word)
  3. 判定成立条件必须首先回溯程序的起始位置,不然程序依旧会报错,原因是得到成立结果的同时,可能也已经遍历完所有的matrix元素,此时,跳出回溯的不成立条件也达到了,如if row < 0 or row >= len(board) or col < 0 or col >= len(board[0]):也是成立,若是将其放在回溯程序起始位置,则最终会返回一个False
  4. 对于这种从任意起点开始判定是否存在路径的方法,不如将循环主体放在调用回溯程序的主程序中,因为此时,只需有一个满足即可进行范围,有利于程序的提前终止,本题就是采用了将两个for循环放在了主程序中,遍历每个元素并进行回溯。
  5. 事实上,这道题有个bug,在输入为[["a, a"]], "a, a, a"时,自己写的程序在本机跑的结果与提交程序跑出来的结果不同,因此,本博客也将能通过审核的答案放在了参考答案中。

参考资料

[1] https://blog.csdn.net/fuxuemingzhu/article/details/79386066

猜你喜欢

转载自blog.csdn.net/Dby_freedom/article/details/84584798