【Leetcode】79. 单词搜索

84 阅读3分钟

题目描述

在这里插入图片描述

// 79. 单词搜索


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

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


题解

// 回溯搜索
// 特殊情况判断,如果board的行row或列col为0,直接false。
// 构建direction数组,将矩阵移动的上左下右四个方向保存起来用于搜索,
// 构建marked boolean矩阵,与board同规模,用于标记board中遍历元素是否被使用,
// 将board和word作为类变量保存,减少backtracking参数,
// 双for循环遍历board的所有位置,i遍历行数row,j遍历列数col,
// 调用backtracking回溯搜索函数,传入行数row,列数col,遍历元素索引i和j,和
// word的遍历索引index。
// 
// 定义backtracking回溯搜索函数,传入行数row,列数col,遍历元素索引i和j,和
// word的遍历索引index。老样子,定义递归结束条件:如果word索引元素index到达
// 了word的末位,则返回当前遍历位字符board[i][j]是否与word当前遍历字符
// word.charAt(index)相等的布尔值。
// 之后条件判断当前遍历字符board[i][j]是否等于word当前遍历字符 word.charAt(index)
// 如果不相等返回false;
// 相等的话则将marked的相应位marked[i][j]标记为true(已使用),然后for循环
// 遍历direction四个方位int[] dic,将方位的第一个元素(行坐标增量)
// 累加给i,记为x,方位dic的第二个元素(列坐标增量)累加给j,记为y。
// 则board[x][y]为根据direction方向移动后的坐标,
// 条件判断,如果0<=x<row,且0<=y<col,且marked[x][y]为false,即board[x][y]
// 没被使用过。则递归调用backtracking,传入的board遍历位置更新为x和y,
// word遍历位置index更新为index+1。如果调用结果为true,
// 则直接返回true。四个方向for循环搜索之后,将marked[i][j]位置置为false,
// 
// 回到双for循环,循环之后直接返回false(如果没搜索到,则不会返回true,
// 所以返回false。
// 执行用时:93 ms, 在所有 Java 提交中击败了28.02%的用户
// 内存消耗:36.2 MB, 在所有 Java 提交中击败了98.60%的用户
class Solution {
	private int[][] direction = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};
    private boolean[][] marked;
	private char[][] board;
	private String word;
	
	public boolean exist(char[][] board, String word) {
		int row = board.length;
		int col = board[0].length;
		if (row == 0 || col == 0) return false;
		marked = new boolean[row][col];
		this.board = board;
		this.word = word;
		for (int i = 0; i < row; i++) {
			for (int j = 0; j < col; j++) {
				if (backtracking(row, col, i, j, 0))
					return true;
			}
		}
		return false;
    }
	
	public boolean backtracking(int row, int col, int i, int j, int index) {
		if (index == word.length() - 1) {
			return (board[i][j] == word.charAt(index));
		}
		if (board[i][j] == word.charAt(index)) {
			marked[i][j] = true;
			for (int[] dic: direction) {
				int x = i + dic[0];
				int y = j + dic[1];
				if (0 <= x && x < row && 0 <= y && y < col && !marked[x][y]) {
					if (backtracking(row, col, x, y, index + 1)) {
						return true;
					}
				}
			}
			marked[i][j] = false;
		}
		return false;
	}
}