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. JS0热身运动

    热身热身小知识点: JS中如何获取元素: 1 通过ID名称来获取:document get element by id  -->document.getElementById() 2 .... ...

  2. SQL_server 的基本操作

    1.---------------数据库基本操作 主键 : 1.不重复 2.不为NULL外键 1.取消重复行(消除完全一样的行,保留一行)select distinct cloumname1,clou ...

  3. Scoket简介

    我们很多人都听说过Socket编程也称网络编程,在我们当今的社会中网络已经深入到我们的生活中了,计算机的网络通信也成为我们生活中必不可少的一部分.而实现我们网络通信就得依靠网络编程,让我们的计算机之间 ...

  4. UDP—Socket,套接字聊天简单的聊天程序。

    思路:(发送端) 1.既然需要聊天.就应该怎么建立聊天程序,,DatagramSocket对象http://www.w3cschool.cc/manual/jdk1.6/ DatagramSocket ...

  5. Asp.Net Mvc4 Ajax提交数据成功弹框后跳转页面

    1.cshtml页面代码 @model Model.UserInfo @{     ViewBag.Title = "Edit"; var options = new AjaxOp ...

  6. 关于jQuery,$(":button") 中的冒号是什么意思?

    $(":button") 表示匹配所有的按钮.$("input:checked")表示匹配所有选中的被选中元素(复选框.单选框等,不包括select中的opti ...

  7. React初探

    经过几天根据官方文档和博园中一些大牛的文章,在了解过基础的语法和组件后,总结一下: 1.第一件事就是分析界面,理想状态下是让每个组件只做一件事情,也就是单一职责,相互嵌套.我认为: 构建组件树,整体的 ...

  8. SQLITE和QT

    sqlite3数据库支持事务 例如: BEGIN DEFERRED TRANSACTION; INSERT INTO main.test_transaction (test_unique) VALUE ...

  9. SlidesJS 3.0.4 在手机上遇到的一些问题及解决办法

    SlidesJS 3.0.4 http://slidesjs.com 在手机上遇到的一些问题及解决办法 1.手机上打开有sliderjs的页面后, 切换到别的页面再回来时, sliderjs部分不能滑 ...

  10. django添加静态文件

    最近做了一个todolist webapp,需要稍微添加css时候又忘记django的添加方法了,查看了以前的项目才想起来,所以记录一下. 1.settings.py 将以下代码放到最下面 STATI ...