[LeetCode#212]Word Search II
2015-08-28 23:55
246 查看
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 =
Return
Note:
You may assume that all inputs are consist of lowercase letters
Analysis:
Solution:
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; } }
相关文章推荐
- 微信读书来了,说好的全民刷书呢?
- Linux备份与恢复
- 企业管理之客户之道
- vsftpd遇到“refusing to run with writable root inside chroot”错误
- RESTful HTTP的实践
- JSOI2013编程作业
- XenDesktop 设置上班高峰期前预先启动虚拟桌面
- oracle之安装
- My Booklist
- Hadoop里的数据挖掘应用-Mahout——学习笔记<三>
- swift - The Proxy Pattern
- 信号量 互斥锁 条件变量的区别
- OSPF特殊区域之totally stub
- 开源框架-ormlite-android数据库的使用
- iOS之Operation Queues 和 Grand Central Dispatch
- 华为OJ题2---字符串最后一个单词的长度
- 详解连接SQL Server数据库的方法,并使用Statement接口实现对数据库的增删改操作
- Spark的Python和Scala shell介绍(翻译自Learning.Spark.Lightning-Fast.Big.Data.Analysis)
- mac 设置 HOMEBREW_GITHUB_API_TOKEN的正确方法
- javascript中的函数Function