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;
}
}

[LeetCode#212]Word Search II的更多相关文章

  1. Java for LeetCode 212 Word Search II

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

  2. [LeetCode] 212. Word Search II 词语搜索 II

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

  3. [LeetCode] 212. Word Search II 词语搜索之二

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

  4. leetcode 79. Word Search 、212. Word Search II

    https://www.cnblogs.com/grandyang/p/4332313.html 在一个矩阵中能不能找到string的一条路径 这个题使用的是dfs.但这个题与number of is ...

  5. 【leetcode】212. Word Search II

    Given an m x n board of characters and a list of strings words, return all words on the board. Each ...

  6. 212. Word Search II

    题目: Given a 2D board and a list of words from the dictionary, find all words in the board. Each word ...

  7. 【LeetCode】212. Word Search II 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 前缀树 日期 题目地址:https://leetco ...

  8. [leetcode trie]212. Word Search II

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

  9. 【leetcode】Word Search II(hard)★

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

随机推荐

  1. jq版本更新后无live函数的处理.

    之前你的代码如果是$("#ele").live("click", function() {    //...});现在要写成$("#ele" ...

  2. .Net程序员学习Linux(二)

    本次知识点:递归命令符,wc命令,文档编辑器 vi的简单使用,文本常用操作命令,find查询文件命令,grep匹配文本中对应的关键字 递归命令符 递归对于程序猿来说不默认,经常用于级联关系,一层套一层 ...

  3. win7下配置apache和php

    1.软件装备 PHP:http://php.net/downloads.php non-thread-safe是非安全线程主要与IIS搭配环境. thread-safe安全线程与Apache搭配环境. ...

  4. C#中Hashtable、Dictionary详解以及写入和读取对比

    转载:http://www.cnblogs.com/chengxingliang/archive/2013/04/15/3020428.html 在本文中将从基础角度讲解HashTable.Dicti ...

  5. 1.redis.3.2 下载,安装、配置、使用 - 1

    1.下载:   2.使用: 挤压之后,使用cmd执行,如下图 redis-server--service-installredis.windows.conf,执行安装 提示成功之后,剩下就好办了, 这 ...

  6. Access restriction:The type JPEGCodec is not accessible due to restriction on required library C:\Program Files\Java\jre6\lib\rt.jar

    解决方法: Project -> Properties -> libraries, 先remove掉JRE System Library,然后再Add Library重新加入. ===== ...

  7. 判断ios是app第一次启动

    首次运行的应用程序加入一些help 或者 宣传动画 现在变的很重要了. 一个有用的例子是发送一个分析实例.这可能是一个很好的方法来确定有多少人下载实用应用程序.有人会说:“但是,嘿,苹果AppStor ...

  8. MvvmCross[翻译] 使用Xamarin与MvvmCross完成一个跨平台App

    总览 原文:https://github.com/MvvmCross/MvvmCross/wiki/Tip-Calc-A-first-app 我们所做的第一个Model-View-ViewModel( ...

  9. ASP.NET Web API教程(六) 安全与身份认证

    在实际的项目应用中,很多时候都需要保证数据的安全和可靠,如何来保证数据的安全呢?做法有很多,最常见的就是进行身份验证.验证通过,根据验证过的身份给与对应访问权限.同在Web Api中如何实现身份认证呢 ...

  10. Sql Server内置函数实现MD5加密

    实例 MD5加密“123456”: HashBytes('MD5','123456') 结果:0xE10ADC3949BA59ABBE56E057F20F883E (提示:看完最后,结果要进行转换.) ...