LeetCode212. Word Search II

来源:互联网 发布:应知故乡事的前一句 编辑:程序博客网 时间:2024/06/06 05:56

LeetCode212. Word Search II

问题描述

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"].

问题分析

问题是给定一个String数组,判断数组内的字符串是否能够在字符表中字符组成。比如eat可以由e(1,3),a(1,2),t(1,1)这三个元素组成。我们可以把这个表看作是图中节点的关联矩阵。那么就是建立节点坐标,然后对每个字符串从头到尾进行匹配就可以了。

代码如下

Java代码

 public List<String> findWords(char[][] board, String[] words) {        List<int []>[] boardNode = new List[26];        //获取board行列        int m = board.length,n = board[0].length;        for (int i = 0; i < m; i++) {            for (int j = 0; j < n; j++) {                int b = board[i][j]-'a';                if(boardNode[b]==null){                    boardNode[b]=new ArrayList<>();                }                boardNode[b].add(new int[]{i,j});            }        }        Set<String> res= new HashSet<>();        for (String word:words             ) {            if(boardNode[word.charAt(0)-'a']!=null){                for (int[] child: boardNode[word.charAt(0)-'a']                        ) {                    if(search(word,0,board,child[0],child[1],new boolean[m][n])){                        res.add(word);                        break;                    }                }            }        }        return new ArrayList<>(res);    }    boolean search(String word,int index,char[][] board,int i,int j, boolean visited[][]){        //如果当前单元格已经完成        if(index==word.length()) return true;            //如果越界或者当前单元格已经访问过,返回False        if(i==board.length||i<0) return false;        if(j==board[0].length||j<0) return false;        if(visited[i][j])  return false;        if(word.charAt(index)==board[i][j]){            //如果当前单元格符合要求            visited[i][j]=true;            //继续递归            if(search(word,index+1,board,i+1,j,visited)||search(word,index+1,board,i-1,j,visited)                    || search(word,index+1,board,i,j+1,visited)|| search(word,index+1,board,i,j-1,visited))                return true;            visited[i][j]=false;        }        return false;    }

Java代码改进

因为上述代码的运行时间太差了,应该怎么优化呢。上述代码因为对所有的字符串都进行完整的判断,如果出现两个重复的字符串asdasd,asdasd那么仍然会完成两个递归,如果俩个字符串由大量的相同部分。asdasdfff,asdasdeee,也会完成两个递归,这样会浪费大量的时间,那么如何对上述算法进行优化呢。我们之前所写的Trie类型就起到了作用,将字符串数组表达为Trie树结构。对这个Trie树进行判断,这样重复的部分就只需要进行一次递归就行了。

在递归过程中,如果发现符合条件的字符串就添加到结果中

public List<String> findWords(char[][] board, String[] words) {    List<String> res = new ArrayList<>();    TrieNode root = buildTrieNode(words);    for (int i = 0; i < board.length; i++) {        for (int j = 0; j < board[0].length; j++) {            dfs(board, i, j, root, res,new StringBuilder());        }    }    return res;}void dfs(char[][] board,int i,int j,TrieNode trieNode,List<String> res,StringBuilder stringBuilder){    char c = board[i][j];    int ci = c-'a';    //如果当前board已被使用或者不符合trie树的结构    if(c=='#'||trieNode.children[ci]==null) return;    trieNode  = trieNode.children[ci];    stringBuilder.append(c);    if(trieNode.isEnd){        res.add(stringBuilder.toString());        trieNode.isEnd =false;    }    board[i][j]='#';    if(i>0) dfs(board,i-1,j,trieNode,res,stringBuilder);    if(j>0) dfs(board,i,j-1,trieNode,res,stringBuilder);    if(j+1<board[0].length) dfs(board,i,j+1,trieNode,res,stringBuilder);    if(i+1<board.length) dfs(board,i+1,j,trieNode,res,stringBuilder);    stringBuilder.deleteCharAt(stringBuilder.length()-1);    board[i][j]=c;}TrieNode buildTrieNode(String[] words){    TrieNode root = new TrieNode();    TrieNode node ;    for (String word:words            ) {        node=root;        for (int i = 0; i < word.length(); i++) {            int c= word.charAt(i)-'a';            if(node.children[c]==null) node.children[c]= new TrieNode();            node = node.children[c];        }        node.isEnd=true;    }    return root;}class TrieNode{    TrieNode[] children = new TrieNode[26];    boolean isEnd = false;}

LeetCode学习笔记持续更新
GitHub地址 https://github.com/yanqinghe/leetcode
CSDN博客地址 http://blog.csdn.net/yanqinghe123/article/category/7176678

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 新车底盘被刮了怎么办 车侧面刮凹了怎么办 憋气久了想呕吐怎么办 19岁网贷欠了3万怎么办 大学生欠2w网贷怎么办 当兵去了网贷怎么办 考公安视力不过关怎么办 身份证号和姓名电话泄露了怎么办 黑色裙子被染色了怎么办 戴墨镜鼻子太塌怎么办 戴墨镜鼻子有印怎么办 戴眼镜鼻梁塌了怎么办 站的时间长了腿疼怎么办 小孩腿筋拉伤了怎么办 走多了小腿骨疼怎么办 走多了一个腿疼怎么办 走太多路腿酸痛怎么办 老年人脚肿并痛怎么办 孩子蛙跳肌后大腿痛怎么办 走路久了腿酸怎么办 走路多了膝盖痛怎么办 走路多了小腿痛怎么办 走多了腿疼怎么办 小腿走多了酸痛怎么办 腿肚受凉了酸痛怎么办 晚上腿疼的睡不着觉怎么办 走路走多了腿酸怎么办 跳完蛙跳大腿疼怎么办 走路走多了脚疼怎么办 走太多路脚酸痛怎么办 走路走的腿酸痛怎么办 路走得太多腿疼怎么办 走路走的足弓疼怎么办 走路走多了膝盖怎么办 2岁宝宝走路一只脚内八字怎么办 6岁宝宝o型腿怎么办 一岁宝宝o型腿怎么办 宝宝一岁o型腿怎么办 宝宝一周两个月走路弓着腿怎么办 宝宝腿走路膝盖弯曲怎么办 两岁宝宝不爱走路怎么办