leetcode [79. 单词搜索](https://leetcode-cn.com/problems/word-search/)

leetcode 79. 单词搜索

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

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

示例 1:

leetcode [79. 单词搜索](https://leetcode-cn.com/problems/word-search/)_第1张图片

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

示例 2:

leetcode [79. 单词搜索](https://leetcode-cn.com/problems/word-search/)_第2张图片

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

示例 3:

leetcode [79. 单词搜索](https://leetcode-cn.com/problems/word-search/)_第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

  • boardword 仅由大小写英文字母组成

进阶:你可以使用搜索剪枝的技术来优化解决方案,使其在 board 更大的情况下可以更快解决问题?

Related Topics

数组

回溯

矩阵

递归+回溯

word可能以二维矩阵中的任意一个点为起点,所以遍历每一个点作为起点。

递归遍历每一个点是否匹配,需要二维标记数组标记哪一位置被选取,进行回溯。

  • 如果当前字母不匹配,说明这一条路径不通,返回false。

  • 如果当前注明匹配:

    • 已经匹配到最后一个,直接返回true。

    • 不是最后一个,递归当前位置的上下左右四个位置判断,进行递归。

      • 必须保证上下左右位置下标合法,而且没有被访问过。

    • 如果没有找到,回溯,返回false。

class Solution {
    private int[][] directions = new int[][]{{-1,0},{1,0},{0,-1},{0,1}};
    public boolean exist(char[][] board, String word) {
        int m = board.length;
        int n = board[0].length;
        boolean[][] visited = new boolean[m][n];
        //判断以board[i][j]为起点 是否能构成单词word
        for(int i = 0 ; i < m;i++){
            for(int j = 0; j < n;j++){
                if(exist(board,i,j,word,0,visited)){
                    return true;
                }
            }
        }
        return false;
    }
    //i ,j表示board递归的位置 index 表示需要找到word中哪一位的字母
    public boolean exist(char[][] board,int i,int j,String word,int index,boolean[][] visited){
        if(board[i][j] != word.charAt(index)){//字母不匹配
            return false;
        }else if(index == word.length()-1){ //当最后一个字母匹配成功 也就是下标为length-1 表示已经找到
            return true;
        }
        //匹配成功 word单词没有匹配完
        // 标记
        visited[i][j] = true;
        //上下左右 进行递归
​
        int m = board.length;
        int n = board[0].length;
        for(int[] direction : directions){
            //计算下标
            int newi = i+direction[0];
            int newj = j+direction[1];
            //下标合法
            if(newi>=0 && newi < m && newj>=0 && newj < n){
                //保证没有被访问过
                if(!visited[newi][newj]){
                    //找到了单词 直接返回
                    if(exist(board,newi,newj,word,index+1,visited)){
                        return true;
                    }
                }
            }
        }
        // 没有找到 回溯
        visited[i][j] = false;
        return false;
    }
}
解答成功:
            执行耗时:112 ms,击败了46.12% 的Java用户
            内存消耗:39.7 MB,击败了15.46% 的Java用户

改进:可以将标记的布尔类型数组不适用,直接board中进行标记。

先保存board[i][j]的值,然后用特殊字符#代替,不匹配的时候再回溯回来。(前提:矩阵中只有字母)

class Solution {
    private int[][] directions = new int[][]{{-1,0},{1,0},{0,-1},{0,1}};
    public boolean exist(char[][] board, String word) {
        int m = board.length;
        int n = board[0].length;
        //判断以board[i][j]为起点 是否能构成单词word
        for(int i = 0 ; i < m;i++){
            for(int j = 0; j < n;j++){
                if(exist(board,i,j,word,0)){
                    return true;
                }
            }
        }
        return false;
    }
    public boolean exist(char[][] board,int i,int j,String word,int index){
        if(board[i][j] != word.charAt(index)){//字母不匹配
            return false;
        }else if(index == word.length()-1){ //当最后一个字母匹配成功 也就是下标为length-1 表示已经找到
            return true;
        }
        //匹配成功 word单词没有匹配完
        // 标记
        char c = board[i][j];
        board[i][j]='#';
        //上下左右 进行递归
        int m = board.length;
        int n = board[0].length;
        for(int[] direction : directions){
            //计算下标
            int newi = i+direction[0];
            int newj = j+direction[1];
            //下标合法
            if(newi>=0 && newi < m && newj>=0 && newj < n){
                if(exist(board,newi,newj,word,index+1)){
                    return true;
                }
            }
        }
        // 没有找到 回溯
        board[i][j] = c;
        return false;
    }
}
解答成功:
            执行耗时:110 ms,击败了48.05% 的Java用户
            内存消耗:39.2 MB,击败了35.23% 的Java用户

你可能感兴趣的:(leetcode,leetcode,算法,职场和发展)