前端重拾算法数据结构一个月(7)

136 阅读3分钟

第七天

今天要学习的主题是,搜索与回溯算法。那先了解一下DFS和BFS吧。

DFS深度优先搜索

是沿着树的深度遍历树的节点,尽可能深的搜索树的分支。在每个分岔路的时候做标记,当由一条路走到终点之后就回溯到上一个分岔路走另一条路,直到走完所有的路。 DFS搜索即是暴力搜索:把一条路走到底之后再回溯。

BFS广度优先搜索

它是一层一层地搜索,每一层搜索完了才会搜索下一层。 它的优势是能够找到最短的路径

来做一题理解一吧,感觉第一题看起来就难难dei

十九题

剑指 Offer 12. 矩阵中的路径

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

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

示例:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

思路: 本题的话感觉有点像走迷宫,那应该是使用深度优先搜索的方法来解。我的思路我一开始是默认他从左上角进来(但其实不是,这个后面说说)。想象自己就在这个“迷宫”里面走,可以上下左右走,通过判断下一步是否是自己需要的字符来决定要不要往那边走。

function exist(board: string[][], word: string): boolean {
    const wordArr = word.split("")
    const lineNum = board.length - 1
    const colNum = board[0].length - 1
    let i = 0
    let j = 0
    const z = [board[0][0]] //走到(0,0)的位置
    board[0][0] = ""            //将(0,0)设为空字符串
    let result = null
    const dfs = (i: number, j: number, z: string[], board: string[][]) => {
      const Arr = [
        { item: board[i + 1 > lineNum ? i : i + 1][j], index: [i + 1, j] },
        { item: board[i][j + 1 > colNum ? j : j + 1], index: [i, j + 1] },
        { item: board[i - 1 < 0 ? i : i - 1][j], index: [i - 1, j] },
        { item: board[i][j - 1 < 0 ? j : j - 1], index: [i, j - 1] },
      ]
      const filterArr = Arr.filter((item) => item.item === wordArr[z.length])
      if (filterArr.length > 0) {
        filterArr.forEach((item) => {
          z.push(item.item)
          board[item.index[0]][item.index[1]] = ""
          i = item.index[0]
          j = item.index[1]
          dfs(i, j, z, board)
        })
      } else {
        if (JSON.stringify(z) === JSON.stringify(wordArr)) {
          return (result = true) 
        }
        return (result = false)
      }
    }
    dfs(i, j, z, board)
    return result
};

这样确实可以得到从左上角进入的题目,但是!题目里没有提到说一定是从左上角进入,也就是说它其实是想让我们做到,在表中搜索任何一个可以进入的点,然后从那个点出发,找到任何可以满足的可能。于是我只能先在数组中去查找所有 输入的字符串的第一个字符 ,作为可以启动的点。

function exist(board: string[][], word: string): boolean {
    const newBoard = board
    const wordArr = word.split("")
    const lineNum = board.length - 1
    const colNum = board[0].length - 1
    let i = 0
    let j = 0
    let z = []
    let result = null
    const firstLocation: [number, number][] = []
    board.forEach((one, index) => {
      one.forEach((two, index2) => {
        if (two === wordArr[0]) {
          firstLocation.push([index, index2])
        }
      })
    })

    const dfs = (i: number, j: number, z: string[], board: string[][]) => {
      const Arr = [
        { item: board[i + 1 > lineNum ? i : i + 1][j], index: [i + 1, j] },
        { item: board[i][j + 1 > colNum ? j : j + 1], index: [i, j + 1] },
        { item: board[i - 1 < 0 ? i : i - 1][j], index: [i - 1, j] },
        { item: board[i][j - 1 < 0 ? j : j - 1], index: [i, j - 1] },
      ]
      const filterArr = Arr.filter((item) => item.item === wordArr[z.length])
      if (filterArr.length > 0) {
        filterArr.forEach((item) => {
          z.push(item.item)
          board[item.index[0]][item.index[1]] = ""
          i = item.index[0]
          j = item.index[1]
          dfs(i, j, z, board)
        })
      } else {
        if (JSON.stringify(z) === JSON.stringify(wordArr)) {
          return (result = true)
        }
        return (result = false)
      }
    }

    const back: boolean[] = firstLocation.map((item) => {
      i = 0
      j = 0
      z = []
      result = null
      const boards = newBoard
      z.push(boards[item[0]][item[1]])
      board[item[0]][item[1]] = ""
      i = item[0]
      j = item[1]
      dfs(i, j, z, boards)
      return result
    })

    return back.includes(true)
};

本来以为是很简单0.0结果写了两小时,不过就完全是靠自己的思路解题的了。

代码敲多了一定要起来走走喝水,要温故而知新。

下面是我的文章会引用到的作者和他的文章,都是跟着它学的,感谢。

作者:Krahets 链接:leetcode.cn/leetbook/re… 来源:力扣(LeetCode)