zoukankan      html  css  js  c++  java
  • 【LeetCode】面试题12. 矩阵中的路径

    题目:

    思路:

    因为可以从矩阵中任意一格开始,所以拿到题之后的思路为: 遍历整个矩阵,尝试把每个点当作起始点去搜索路径,直到找到或者遍历完。考虑到有点暴力,感觉不是最优方法,所以一直在思考更优的方法(也被它动态规划的标签误导了),陷入了瓶颈,没有把之前的暴力思路抽象到深度优先搜索的方法论。
    另外一直在把思路复杂化,考虑记录每次进入某个节点的方向,避免形成循环。而参考了代码中的思路之后,将当前值置为"/",避免了循环。从而能够抽象到特别简单的DFS中,只需要考虑边界就可以了,避免了复杂的条件判断。
    也想到了另一个方法: 对整个矩阵遍历K轮,第k轮遍历找到矩阵中等于目标字符串位置k的字符,查看该位置的上下左右,是否已经组成了前k-1个目标字符串,需要注意的点有: 避免循环,到达某个点的路径可能有多条,都需要记录下来。

    代码:

    Python

    # Solution1 84/87超时
    # [["A","B","C","E"],["S","F","E","S"],["A","D","E","E"]] "ABCESEEEFS"
    # [["a"]] "a"
    # [["a", "a"], ["a", "a"]]  "aaaaa"
    import copy
    class Solution(object):
        def exist(self, board, word):
            """
            :type board: List[List[str]]
            :type word: str
            :rtype: bool
            """
            x = len(board)
            y = len(board[0])
            # 构造now记录每个位置的当前路径[[[set(), set()], []], [[], []]]
            # 每个点通过一个list记录,有几条路径list中就有几个元素,每个元素是set,保证路径不重复
            # 构造过程也是第一个目标字符的遍历过程
            now = list()
            for i in range(x):
                tmp = list()
                for j in range(y):
                    if board[i][j] == word[0]:  # 目标字符串长度为1的情况
                        if len(word) == 1:
                            return True
                        # 保证是list(set(tuple))结构
                        a = set()
                        a.add((i, j))
                        tt = list()
                        tt.append(a)
                        tmp.append(tt)
                    else:
                        tmp.append(list())
                now.append(tmp)
            # 遍历剩余目标字符
            for c in range(1, len(word)):
                # 因为会修改now,避免修改后的now被用于当前轮次
                pre = copy.deepcopy(now)
                this_char = word[c]
                for i in range(x):
                    for j in range(y):
                        now[i][j] = list()
                        # 遍历整个矩阵,对等于当前目标字符的位置。查看它的上下左右,是否存在长度为c的前缀路径,把它们全部找出来
                        if board[i][j] == this_char:
                            pre_list = list()
                            if i - 1 >= 0 and len(pre[i-1][j]) > 0:
                                pre_list.extend(pre[i-1][j])
                            if j - 1 >= 0  and len(pre[i][j-1]) > 0:
                                pre_list.extend(pre[i][j-1])
                            if i + 1 < x and len(pre[i+1][j]) > 0:
                                pre_list.extend(pre[i+1][j])
                            if j + 1 < y and len(pre[i][j+1]) > 0:
                                pre_list.extend(pre[i][j+1])
                            # 对每一个前缀路径,添加当前节点
                            # 如果重复则整个前缀路径失效,判断是否找到
                            for e in pre_list:
                                ee = copy.deepcopy(e)  # 这里不copy会修改pre的数据??
                                ee.add((i, j))
                                if len(ee) == len(word):
                                    return True
                                if len(ee) == (c+1):
                                    now[i][j].append(ee)
            return False
    
    # Solution2
    class Solution(object):
        def exist(self, board, word):
            """
            :type board: List[List[str]]
            :type word: str
            :rtype: 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
                tmp, board[i][j] = 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] = tmp
                return res
            # 把每个节点作为起始点开始遍历
            for i in range(len(board)):
                for j in range(len(board[0])):
                    if dfs(i, j, 0): return True
            return False
    

    相关问题

  • 相关阅读:
    POJ 3041 Asteroids 最小点覆盖 == 二分图的最大匹配
    POJ 3083 Children of the Candy Corn bfs和dfs
    POJ 2049 Finding Nemo bfs 建图很难。。
    POJ 2513 Colored Sticks 字典树、并查集、欧拉通路
    POJ 1013 Counterfeit Dollar 集合上的位运算
    POJ 2965 The Pilots Brothers' refrigerator 位运算枚举
    无聊拿socket写的100以内的加法考试。。。
    POJ 1753 Flip Game
    初学socket,c语言写的简单局域网聊天
    汇编语言 复习 第十一章 标志寄存器
  • 原文地址:https://www.cnblogs.com/cling-cling/p/12956930.html
Copyright © 2011-2022 走看看