zoukankan      html  css  js  c++  java
  • [LeetCode#212]Word Search II

    Problem:

    Given a 2D board and a list of words from the dictionary, find all words in the board.

    Each word must 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 in a word.

    For example,
    Given words = ["oath","pea","eat","rain"] and board = 

    [
      ['o','a','a','n'],
      ['e','t','a','e'],
      ['i','h','k','r'],
      ['i','f','l','v']
    ]
    

    Return ["eat","oath"].

    Note:
    You may assume that all inputs are consist of lowercase letters a-z.

    Analysis:

    This problem is a very typical problem for using DFS. Search on a graph(matrix), find out the path to reach certain goal. At each vertix, we could follow all out edges. 
    
    Key points:
    1. Every gird on the matrix could be treated a start point. 
    for (int i = 0; i < board.length; i++) {
        for (int j = 0; j < board[0].length; j++) {
            searchWord(board, i, j, "", visited, hash_set, ret);
        }
    }
    Before entering the recursive call, we only specify the index(i, j). And only at the recursive funtion, we really add the character at grid(i, j) into our temporary path. This design could have following benefits:
    1. When we fork out search branch(left, right, above, below), we don't need to check if the index(i, j) is valid, which could make the code quite concise. 
    ------------------------------------------------------------
    searchWord(board, i-1, j, cur_str, visited, hash_set, ret);
    searchWord(board, i+1, j, cur_str, visited, hash_set, ret);
    searchWord(board, i, j-1, cur_str, visited, hash_set, ret);
    searchWord(board, i, j+1, cur_str, visited, hash_set, ret);
    -----------------------------------------------------------
    To avoid invalid index, we could simplily do it at the beginning of the recursive funtion, when the index was just passed in.
    if (i < 0 || j < 0 || i >= board.length || j >= board[0].length || visited[i][j])
        return;
    
    2. It is easy to recover changed state(When back tracking).
    Let us suppose you change the state before enter the searchWord.
    for (int i = 0; i < board.length; i++) {
        for (int j = 0; j < board[0].length; j++) {
            visited[i][j] = true;
            searchWord(board, i, j, "", visited, hash_set, ret);
            visited[i][j] = true;
        }
    }
    To make all changed states could be recovered, you have to do above recover thing for all forked branch.
    visited[i-1][j] = true;
    searchWord(board, i-1, j, cur_str, visited, hash_set, ret);
    visited[i-1][j] = false;
    visited[i+1][j] = true;
    searchWord(board, i+1, j, cur_str, visited, hash_set, ret);
    visited[i+1][j] = false;
    visited[i][j-1] = true;
    searchWord(board, i, j-1, cur_str, visited, hash_set, ret);
    visited[i][j-1] = false;
    visited[i][j+1] = true;
    searchWord(board, i, j+1, cur_str, visited, hash_set, ret);
    visited[i][j+1] = false;
    
    How ugly? Right! What'more!!! You need to check is visisted[i][j] is valid for every forked branch. 
    Sky: Since we do the same recover work for all grid on the matrix, we do not do it together at recursive call?
    
    
    3. For this DFS problem, each grid could go four directions. To avoid the path back to visited grid, thus result in infinite loop, we should record all gird we have visited. 
    if (i < 0 || j < 0 || i >= board.length || j >= board[0].length || visited[i][j])
        return;
    visited[i][j] = true;
    check and fork ...        
    visited[i][j] = false;
    
    Since for each grid, we actually search the whole matrix, the search cost is O(m*n).
    There are m*n grids in total, Thus the overall time complexity is O(m^2*n^2).

    Solution:

    public class Solution {
        public List<String> findWords(char[][] board, String[] words) {
            if (board == null || words == null)
                throw new IllegalArgumentException("Plese check the arguments passed into the funtion");
            ArrayList<String> ret = new ArrayList<String> ();
            if (board.length == 0)
                return ret;
            HashSet<String> hash_set = new HashSet<String> ();
            boolean[][] visited = new boolean[board.length][board[0].length];
            for (int i = 0; i < words.length; i++)
                hash_set.add(words[i]);
            for (int i = 0; i < board.length; i++) {
                for (int j = 0; j < board[0].length; j++) {
                    searchWord(board, i, j, "", visited, hash_set, ret);
                }
            }
            return ret;
        }
        
        
        private void searchWord(char[][] board, int i, int j, String cur_str, boolean[][] visited, HashSet<String> hash_set, ArrayList<String> ret) {
            if (i < 0 || j < 0 || i >= board.length || j >= board[0].length || visited[i][j])
                return;
            visited[i][j] = true;
            cur_str = cur_str + board[i][j];
            if (hash_set.contains(cur_str))
                ret.add(cur_str);
            searchWord(board, i-1, j, cur_str, visited, hash_set, ret);
            searchWord(board, i+1, j, cur_str, visited, hash_set, ret);
            searchWord(board, i, j-1, cur_str, visited, hash_set, ret);
            searchWord(board, i, j+1, cur_str, visited, hash_set, ret);
            visited[i][j] = false;
        }
    }
  • 相关阅读:
    美团容器平台架构及容器技术实践
    【人物志】美团首席科学家夏华夏:不断突破边界的程序人生
    Category 特性在 iOS 组件化中的应用与管控
    浅谈大型互联网企业入侵检测及防护策略
    【基本功】深入剖析Swift性能优化
    CAT 3.0 开源发布,支持多语言客户端及多项性能提升
    安装window下的redis,redis可视化管理工具(Redis Desktop Manager)安装,基础使用,实例化项目
    .Net Core Redis的使用
    焦点IT Redis安装与配置( Windows10 或Windows server)
    用VScode配置Python开发环境
  • 原文地址:https://www.cnblogs.com/airwindow/p/4768170.html
Copyright © 2011-2022 走看看