zoukankan      html  css  js  c++  java
  • 79. Word Search

    题目:

    Given a 2D board and a word, find if the word exists in the grid.

    The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.

    For example,
    Given board =

    [
      ["ABCE"],
      ["SFCS"],
      ["ADEE"]
    ]
    

    word = "ABCCED", -> returns true,
    word = "SEE", -> returns true,
    word = "ABCB", -> returns false.

    链接:  http://leetcode.com/problems/word-search/

    题解:

    在一个char[][] board里找单词。基本就是无向图找connected components,用dfs+bfs就可以了,还要加上back tracking。这道是旧题,好像新题里这样的题目很多。要留意边界条件的判断,以及dfs和bfs怎样写比较简洁。

    Time Complexity - O(mn * 26L), Space Complexity - O(mn)。

    public class Solution {
        public boolean exist(char[][] board, String word) {
            if(board == null || word == null || board.length == 0 || word.length() == 0)
                return false;
            
            for(int i = 0; i < board.length; i++) {
                for(int j = 0; j < board[0].length; j++) {
                    if(dfs(board, word, i, j, 0))
                        return true;
                }
            }
            
            return false;
        }
        
        
        private boolean dfs(char[][] board, String word, int i, int j, int pos) {
            if(pos == word.length())
                return true;
            if(i >= board.length || i < 0 ||  j < 0 || j >= board[0].length)    
                return false;
            if(board[i][j] == '#')
                return false;
            if(board[i][j] != word.charAt(pos))
                return false;
            char tmp = board[i][j];
            board[i][j] = '#';
            boolean res = dfs(board, word, i - 1, j, pos + 1)
                       || dfs(board, word, i + 1, j, pos + 1)
                       || dfs(board, word, i, j - 1, pos + 1)
                       || dfs(board, word, i, j + 1, pos + 1);
            board[i][j] = tmp;
            return res;     
        }
    }

    二刷:

    做题前还是要先想清楚自己想做什么,想怎么做,然后要怎样实现比较好。要先把算法写出来,再把算法转换成code。下面是思路

    1. 这道题我们主要想到了使用DFS来查找单词是否存在
    2. 首先我们判断一下边界
    3. 接下来我们建立一个新的boolean[rowNum][colNum]矩阵visited 来记录在一次dfs中是否遇到以前使用过的元素
    4. 最后,在主函数中我们对board的每一个位置进行一个dfs的查找,假如这个查找tryFindWord()返回true,我们就return true,否则,我们继续下一个位置的查找。
    5. 在用来作DFS的辅助tryFindWord里
      1. 我们接受的变量 board,  visited,  i, j表示当前board中位置, word, pos表示word中的位置
      2. 首先我们判断pos 是否等于word.length(),假如等于,则我们找到一个正确结果,可以返回true
      3. 其次,我们进行剪枝 -  当i和j不在board的范围内, 或者已经被访问过 visited[i][j] = true,或者  board[i][j] != word.charAt(pos), 我们都返回false
      4. 我们设置visited[i][j] = true
      5. 接下来我们进行对当前坐标上下左右四个方向进行dfs。 还可以把这四个方向写成一个global的矩阵,比如int[][] direction = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}}, 然后用一个foreach 循环来处理。
      6. bactracking,设置visited[i][j] = false,我们消除之前操作
      7. 假如四个方向中有一个为true,则我们返回true, 否则四个方向均为false,我们返回false

    Java:

    DFS的深度是单词长度L, DFS branching factor是矩阵元素数m x n,所以时间复杂度是(mn)L

    Time Complexity - O((mn)L), Space Complexity - O(mn)

    public class Solution {
        public boolean exist(char[][] board, String word) {
            if (board == null || word == null || board.length == 0) {
                return false;
            }
            int rowNum = board.length, colNum = board[0].length;
            boolean[][] visited = new boolean[rowNum][colNum];
            for (int i = 0; i < rowNum; i++) {
                for (int j = 0; j < colNum; j++) {
                    if (tryFindWord(board, visited, i, j, word, 0)) {
                        return true;
                    }
                }
            }
            return false;
        }
        
        private boolean tryFindWord(char[][] board, boolean[][] visited, int i, int j, String word, int pos) {
            if (pos == word.length()) {
                return true;
            }
            if (i < 0 || j < 0 || i > board.length - 1 || j > board[0].length - 1 || visited[i][j] || board[i][j] != word.charAt(pos)) {
                return false;
            }
            visited[i][j] = true;
            boolean res = tryFindWord(board, visited, i - 1, j, word, pos + 1)
                       || tryFindWord(board, visited, i, j - 1, word, pos + 1)
                       || tryFindWord(board, visited, i + 1, j, word, pos + 1)
                       || tryFindWord(board, visited, i, j + 1, word, pos + 1);
            
            visited[i][j] = false;
            return res;
        }
    }

    使用预先设置好的directions矩阵

    public class Solution {
        private int[][] directions = new int[][] {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
        public boolean exist(char[][] board, String word) {
            if (board == null || word == null || board.length == 0) {
                return false;
            }
            int rowNum = board.length, colNum = board[0].length;
            boolean[][] visited = new boolean[rowNum][colNum];
            for (int i = 0; i < rowNum; i++) {
                for (int j = 0; j < colNum; j++) {
                    if (tryFindWord(board, visited, i, j, word, 0)) {
                        return true;
                    }
                }
            }
            return false;
        }
        
        private boolean tryFindWord(char[][] board, boolean[][] visited, int i, int j, String word, int pos) {
            if (pos == word.length()) {
                return true;
            }
            if (i < 0 || j < 0 || i > board.length - 1 || j > board[0].length - 1 || visited[i][j] || board[i][j] != word.charAt(pos)) {
                return false;
            }
            visited[i][j] = true;
            for (int[] direction : directions) {
                if (tryFindWord(board, visited, i + direction[0], j + direction[1], word, pos + 1)) {
                    return true;
                }
            }
            visited[i][j] = false;
            return false;
        }
    }

    三刷:

    要先设计一个boolean[][]矩阵visited,之后再遍历整个board, 遍历的过程中使用DFS来尝试找到解决方案。 注意DFS返回结果的时候,先判断pos 是否等于word.length(), 再判断边界。

    Java:

    public class Solution {
        public boolean exist(char[][] board, String word) {
            if (board == null || word == null || board.length == 0) return false;
            int rowNum = board.length, colNum = board[0].length;
            boolean[][] visited = new boolean[rowNum][colNum];
            for (int i = 0; i < rowNum; i++) {
                for (int j = 0; j < colNum; j++) {
                    if (exist(board, visited, word, i, j, 0)) return true;
                }
            }
            return false;
        }
        
        private boolean exist(char[][] board, boolean[][] visited, String word, int i, int j, int pos) {
            if (pos == word.length()) return true;
            if (i < 0 || j < 0 || i > board.length - 1 || j > board[0].length - 1) return false;
            if (visited[i][j] || board[i][j] != word.charAt(pos)) return false;
            visited[i][j] = true;
            
            if (exist(board, visited, word, i - 1, j, pos + 1) 
                || exist(board, visited, word, i + 1, j, pos + 1) 
                || exist(board, visited, word, i, j - 1, pos + 1) 
                || exist(board, visited, word, i, j + 1, pos + 1)) return true;
                
            visited[i][j] = false;
            return false;
        }
    }

    Reference:

    https://leetcode.com/discuss/23165/accepted-very-short-java-solution-no-additional-space

    https://leetcode.com/discuss/47314/my-java-solution-15-lines-easy-to-understand

    https://leetcode.com/discuss/23165/accepted-very-short-java-solution-no-additional-space

  • 相关阅读:
    dubbo zookeeper报错failed to connect to server , error message is:No route to host
    linux的ssh命令
    linux的/etc/hosts的作用
    linux如何查看某个pid的进程?
    Nginx配置详解
    nginx基本配置与参数说明以及Nginx中的upstream轮询机制介绍
    Nginx配置upstream实现负载均衡
    nginx简单的nginx.conf配置
    API Gateway性能比较:NGINX vs. ZUUL vs.Cloud Gateway vs. Linkerd[译]
    RabbitMQ 入门【精+转】
  • 原文地址:https://www.cnblogs.com/yrbbest/p/4437124.html
Copyright © 2011-2022 走看看