跳到主要内容

字典树

208. 实现 Trie (前缀树)

Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。

请你实现 Trie 类:

  • Trie() 初始化前缀树对象。
  • void insert(String word) 向前缀树中插入字符串 word
  • boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false
  • boolean startsWith(String prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true ;否则,返回 false
class Trie {
private Trie[] children;
private boolean isEnd;

public Trie() {
children = new Trie[26];
isEnd = false;
}

public void insert(String word) {
Trie node = this;
for (int i = 0; i < word.length(); i++) {
char ch = word.charAt(i);
int index = ch - 'a';
if (node.children[index] == null) {
node.children[index] = new Trie();
}
node = node.children[index];
}
node.isEnd = true;
}

public boolean search(String word) {
Trie node = searchPrefix(word);
return node != null && node.isEnd;
}

public boolean startsWith(String prefix) {
return searchPrefix(prefix) != null;
}

private Trie searchPrefix(String prefix) {
Trie node = this;
for (int i = 0; i < prefix.length(); i++) {
char ch = prefix.charAt(i);
int index = ch - 'a';
if (node.children[index] == null) {
return null;
}
node = node.children[index];
}
return node;
}
}

211. 添加与搜索单词 - 数据结构设计

请你设计一个数据结构,支持 添加新单词 和 查找字符串是否与任何先前添加的字符串匹配 。

实现词典类 WordDictionary

  • WordDictionary() 初始化词典对象
  • void addWord(word)word 添加到数据结构中,之后可以对它进行匹配
  • bool search(word) 如果数据结构中存在字符串与 word 匹配,则返回 true ;否则,返回 falseword 中可能包含一些 '.' ,每个 . 都可以表示任何一个字母。

解法:正常情况下可以直接根据word的长度进行递归搜索。但是这个题目有一个特殊的.字符。所以可以考虑使用递归。

class WordDictionary {
private Trie root;

public WordDictionary() {
root = new Trie();
}

public void addWord(String word) {
root.insert(word);
}

public boolean search(String word) {
return dfs(word, 0, root);
}

private boolean dfs(String word, int index, Trie node) {
if (index == word.length()) {
return node.isEnd();
}
char ch = word.charAt(index);
if (Character.isLetter(ch)) {
int childIndex = ch - 'a';
Trie child = node.getChildren()[childIndex];
if (child != null && dfs(word, index + 1, child)) {
return true;
}
} else {
for (int i = 0; i < 26; i++) {
Trie child = node.getChildren()[i];
if (child != null && dfs(word, index + 1, child)) {
return true;
}
}
}
return false;
}
}

class Trie {
private Trie[] children;
private boolean isEnd;

public Trie() {
children = new Trie[26];
isEnd = false;
}

public void insert(String word) {
Trie node = this;
for (int i = 0; i < word.length(); i++) {
char ch = word.charAt(i);
int index = ch - 'a';
if (node.children[index] == null) {
node.children[index] = new Trie();
}
node = node.children[index];
}
node.isEnd = true;
}

public Trie[] getChildren() {
return children;
}

public boolean isEnd() {
return isEnd;
}
}

212. 单词搜索 II

给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words返回所有二维网格上的单词

单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。

解法:需要从board的每个字符开始,遍历临近的字符,和words数组进行比较是否匹配。如果使用Set那么不好匹配具体的字符。我们需要一个字符一个字符的进行比较。那么久可以考虑是用Tire树。

class Solution {

int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

public List<String> findWords(char[][] board, String[] words) {

Tire tire = new Tire();
for(String word: words){
tire.insert(word);
}
Set<String> ans = new HashSet<String>();

for(int i=0; i< board.length; i++){
for( int j=0; j< board[0].length; j++){
dfs(board, tire, i, j, ans);
}
}
return new ArrayList<String>(ans);

}

public void dfs(char[][] board, Tire now, int i1, int j1, Set<String> ans) {
if (!now.children.containsKey(board[i1][j1])) {
return;
}
char ch = board[i1][j1];
now = now.children.get(ch);
//已经匹配成功
if (!"".equals(now.word)) {
ans.add(now.word);
}
if(!now.children.isEmpty()){
board[i1][j1] = '#';
for (int[] dir : dirs) {
int i2 = i1 + dir[0], j2 = j1 + dir[1];
if (i2 >= 0 && i2 < board.length && j2 >= 0 && j2 < board[0].length) {
dfs(board, now, i2, j2, ans);
}
}
board[i1][j1] = ch;
}

}

}


class Tire {
String word;
Map<Character,Tire> children;
boolean isWord;

public Tire(){
this.word="";
this.children= new HashMap<Character,Tire>();
}

public void insert(String word){
Tire cur =this;
for(int i=0;i < word.length();i++){
char c = word.charAt(i);
if (!cur.children.containsKey(c)) {
cur.children.put(c, new Tire());
}
cur= cur.children.get(c);
}
cur.word = word;
}
}

点我查看更多精彩内容:www.flydean.com关注公众号加我好友
Loading Comments...