[LeetCode] Word Search 的非递归实现

来源:互联网 发布:it技术总监岗位职责 编辑:程序博客网 时间:2024/05/17 17:40

真是孤陋寡闻,直到前些时间才知道有LeetCode这么一个网站。这段时间我正好也在复习数据结构,这样可以用这些题来检验一下学习效果。就从Array分类的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.
For example,
Given board =[
  ["ABCE"],
  ["SFCS"],
  ["ADEE"]
]
word = "ABCCED", -> returns true,
word = "SEE", -> returns true,
word = "ABCB", -> returns false.

思路还是很容易想到的,先通过二重循环找到地一个字母的位置,然后做深度优先搜索(4个方向),参照书上深度优先搜索的递归实现,改一改,调试调试,就通过了。源码如下

class Solution(object):        def __init__(self):        self._next = [(1,0),(0,1),(-1,0),(0,-1)]            def _dfs(self, x, y):        if self._flag == True:            return        if self._count == len(self._word):            self._flag = True             return        for i in range(4):            tx, ty = x + self._next[i][0], y + self._next[i][1]            if 0<=tx<self._row and 0<=ty<self._col and \            self._visited[tx][ty] == 0 and \            self._board[tx][ty] == self._word[self._count]:                self._visited[tx][ty] = 1                self._count += 1                self._dfs(tx,ty)                self._count -= 1                self._visited[tx][ty] = 0                     def exist(self, board, word):        """        :type board: List[List[str]]        :type word: str        :rtype: bool        """                self._row = len(board)                                  #row        self._col = len(board[0])                               #col        self._visited = [[0 for j in range(self._col) ] for i in range(self._row) ]           self._board = board        self._word = word                self._count = 0             self._flag = False                              for row in range(self._row):            for col in range(self._col):                if self._board[row][col] == self._word[0]:                    self._visited[row][col] = 1                    self._count = 1                    self._dfs(row,col)                    if self._flag == True:                        return True                                                            self._visited[row][col] = 0                    self._count = 0        return Falseif __name__ == '__main__':    s = Solution()        board = ["ABCE","SFES","ADEE"]    word = "ABCESEEEFS"    print s.exist(board,word)        board = ["ABCE","SFCS","ADEE","ADEE","ADEE","ADEE"]    word =  "ABCS"    print s.exist(board,word)
因正好在看堆栈相关的内容,所以想用非递归来实现。原来以为能够比较轻松搞定,结果确实比较狼狈,反反复复,把周六、周日都搭上了,最后总算通过。收获是通过这个程序把一些原来没有弄得很清楚的地方理清楚了。即什么时候入栈,什么时候出栈,把什么东西放到堆栈里。对应这个问题,就是什么时候向前走(深度优先),什么时候回退( backtrace),回退到哪一步。

入栈的内容:[x, y, steps ],其中x, y是当前满足要求的节点的坐标,steps是一个列表,存放与(x,y)的四个方向上的邻居节点,前提是这些邻居节点是下一个满足要求的字母。如果没有满足邻居节点,则steps为空,则出栈;如果不为空,则从steps.pop()一个(tx, ty)出来判断,如果(tx, ty)有符合要求邻居节点的则(tx, ty)如站,否则继续从steps.pop(),然后继续判断;如果直到堆栈为空,还没有找到,则返回False,找到返回True。找的过程中必须标记以访问的点,这些点不能再次访问,否则重复了。

代码如下:

class Solution(object):        def _push(self, e):             self._stack.append(e)             def _pop(self):          if len(self._stack)>0:              return self._stack.pop()    #remove last item from list          else:            return None            def _top(self):        if len(self._stack)>0:              return self._stack[-1]                            else:            return None        def _dfs(self, x, y):                if x<0 or y<0:            return False                if self._word[0] == self._board[x][y]:            self._visited[x][y] = 1            self._count = 1            if self._count == len(self._word):                return True                        steps = []            for i in range(3, -1, -1):                tx,  ty  = x + self._next[i][0],  y + self._next[i][1]                if 0<= tx < self._row and 0<= ty < self._col and \                self._visited[tx][ty] == 0 and \                self._word[self._count] == self._board[tx][ty]:                    #self._visited[tx][ty] = 1                    steps.append((tx,ty))                self._push([x,y,steps])                       #print '---'                    else:            return False                while self._top() != None:            #print self._stack            #print self._count            e = self._top()            x, y, steps = e[0], e[1], e[2]            if len(steps) == 0:               #backtrace                self._visited[x][y] = 0                self._count -= 1                self._pop()            else:                             #forward                  x, y = steps.pop()                #if self._word[self._count] == self._board[x][y]:                self._count += 1                self._visited[x][y] = 1                                    if self._count == len(self._word):                    return True                else:                    tsteps = []                    for i in range(3, -1, -1):                        tx,  ty  = x + self._next[i][0],  y + self._next[i][1]                        if 0<= tx < self._row and 0<= ty < self._col and \                        self._visited[tx][ty] == 0 and \                        self._word[self._count] == self._board[tx][ty]:                            #self._visited[tx][ty] = 1                            tsteps.append((tx,ty))                                                if len(tsteps) == 0:                 #backtrace                        self._visited[x][y] = 0                        self._count -= 1                    else:                        self._push([x,y,tsteps])         #forward        return False                def exist(self, board, word):        """        :type board: List[List[str]]        :type word: str        :rtype: bool        """                self._next = [(1,0),(0,1),(-1,0),(0,-1)]        self._row = len(board)                                #row        self._col = len(board[0])                             #col        self._visited = [[0 for j in range(self._col) ] for i in range(self._row) ]           self._board = board        self._word = word                self._stack = []                                      #the stack          self._count = 0                                                      for x in range(self._row):            for y in range(self._col):                self._count = 0                 if self._board[x][y] == self._word[0]:                    if self._dfs(x,y) :                        return True        return Falseif __name__ == '__main__':        s = Solution()        board = ["ABCE","SFES","ADEE"]    #word = "ABCESEEEFS"    word = 'ABCESEEEFS'    print s.exist(board,word)        board = ["ABCE123456","SFCS123456","ADEE123456","ADEE123456","ADEE123456","ADEE123456"]    word =  "ABCB"    print s.exist(board,word)          word =  "ABCA"    print s.exist(board,word)          board = ["ABCE","SFCS","ADEE"]      

LeetCode 有一个好处,提交的程序不通过,它会把测试不通过的测试数据告诉你,这样就方便调试了。构造测试用例真的很重要。



0 0
原创粉丝点击