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;
        }
    }
  • 相关阅读:
    写给新的一年(2015)
    Lucene.Net 入门级实例 浅显易懂。。。
    EF webapi json序列化 表间相互引用 无限循环问题解决方案
    java枚举使用详解,整理的很好,只能收下。。。
    mac
    ASP.NET Web API 全局权限和异常处理
    c# 与 java 语法异同
    tfs 报错解决方案:tf400324
    使用C#开发ActiveX控件
    android 更新listview 其中一行的数据显示
  • 原文地址:https://www.cnblogs.com/airwindow/p/4768170.html
Copyright © 2011-2022 走看看