Go Java算法单词搜索
黄丫丫 人气:0单词搜索
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
- 示例 1:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true
- 示例 2:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE"
输出:true
- 示例 3:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB"
输出:false
提示:
- m == board.length
- n = board[i].length
- 1 <= m, n <= 6
- 1 <= word.length <= 15
board 和 word 仅由大小写英文字母组成
算法:DFS回溯(Java)
- 以"SEE"为例,首先要选起点:遍历矩阵,找到起点S。
- 起点可能不止一个,基于其中一个S,看看能否找出剩下的"EE"路径。
- 下一个字符E有四个可选点:当前点的上、下、左、右。
- 逐个尝试每一种选择。基于当前选择,为下一个字符选点,又有四种选择。
- 每到一个点做的事情是一样的。DFS 往下选点,构建路径。
- 当发现某个选择不对,不用继续选下去了,结束当前递归,考察别的选择。
递归的关键点
- 关注当前考察的点,处理它,其他丢给递归子调用去做。
- 判断当前选择的点,本身是不是一个错的点。
- 剩下的字符能否找到路径,交给递归子调用去做。
- 如果当前点是错的,不用往下递归了,返回false。否则继续递归四个方向,为剩下的字符选点。
那么,哪些情况说明这是一个错的点:
- 当前的点,越出矩阵边界。
- 当前的点,之前访问过,不满足「同一个单元格内的字母不允许被重复使用」。
- 当前的点,不是目标点,比如你想找 E,却来到了 D。
class Solution { public boolean exist(char[][] board, String word) { if (board == null || board.length == 0) { return false; } boolean[][] visited = new boolean[board.length][board[0].length]; char[] chars = word.toCharArray(); for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { if (existHelper(board, visited, chars, i, j, 0)) { return true; } } } return false; } private boolean existHelper(char[][] board, boolean[][] visited, char[] chars, int row, int column, int index) { if (index == chars.length) { return true; } int[][] direction = new int[][]{ {0, 1}, {1, 0}, {0, -1}, {-1, 0} }; if (row >= 0 && row < board.length && column >= 0 && column < board[0].length && board[row][column] == chars[index] && !visited[row][column]) { visited[row][column] = true; for (int[] dir : direction) { int newX = row + dir[0]; int newY = column + dir[1]; if (existHelper(board, visited, chars, newX, newY, index + 1)) { return true; } } visited[row][column] = false; } return false; } }
时间复杂度:O(M*N * 3^L)
空间复杂度:O(M*N)
算法:DFS回溯(Go)
思路同上
func exist(board [][]byte, word string) bool { m, n := len(board), len(board[0]) used := make([][]bool, m) for i := 0; i < m; i++ { used[i] = make([]bool, n) } var canFind func(r, c, i int) bool canFind = func(r, c, i int) bool { if i == len(word) { return true } if r < 0 || r >= m || c < 0 || c >= n { return false } if used[r][c] || board[r][c] != word[i] { return false } used[r][c] = true canFindRest := canFind(r+1, c, i+1) || canFind(r-1, c, i+1) || canFind(r, c+1, i+1) || canFind(r, c-1, i+1) if canFindRest { return true } else { used[r][c] = false return false } } for i := 0; i < m; i++ { for j := 0; j < n; j++ { if board[i][j] == word[0] && canFind(i, j, 0) { return true } } } return false }
时间复杂度:O(M*N * 3^L)
空间复杂度:O(M*N)
加载全部内容