Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补全和拼写检查。
请你实现 Trie 类:
Trie()初始化前缀树对象。void insert(String word)向前缀树中插入字符串word。boolean search(String word)如果字符串word在前缀树中,返回true(即,在检索之前已经插入);否则,返回false。boolean startsWith(String prefix)如果之前已经插入的字符串word的前缀之一为prefix,返回true;否则,返回false。
解法 数组和ascii码实现
思路
利用 ascii 码的特性算出数组的 index
代码
const CHAR_CODE_A = "a".charCodeAt(0);
function toIndex(char: string): number {
return char.charCodeAt(0) - CHAR_CODE_A;
}
class TrieNode {
children: Array<TrieNode | null>;
isEnd: boolean;
constructor() {
this.children = new Array(26).fill(null);
this.isEnd = false;
}
}
class Trie {
private root: TrieNode;
constructor() {
this.root = new TrieNode();
}
insert(word: string): void {
let node = this.root;
for (let i = 0; i < word.length; i++) {
const index = toIndex(word[i]);
if (!node.children[index]) {
node.children[index] = new TrieNode();
}
node = node.children[index];
}
node.isEnd = true;
}
search(word: string): boolean {
let node = this.root;
for (let i = 0; i < word.length; i++) {
const index = toIndex(word[i]);
if (!node.children[index]) {
return false;
}
node = node.children[index];
}
return node.isEnd;
}
startsWith(prefix: string): boolean {
let node = this.root;
for (let i = 0; i < prefix.length; i++) {
const index = toIndex(prefix[i]);
if (!node.children[index]) {
return false;
}
node = node.children[index];
}
return true;
}
}
解法2 map实现
思路
方法的整体逻辑和数组实现一样,只不过换了底层的数据结构,map 适合存储稀疏的数据。
代码
class TrieNode {
children: Map<string, TrieNode>;
isEnd: boolean;
constructor() {
this.children = new Map();
this.isEnd = false;
}
}
class Trie {
private root: TrieNode;
constructor() {
this.root = new TrieNode();
}
insert(word: string): void {
let node = this.root;
for (let char of word) {
if (!node.children.has(char)) {
node.children.set(char, new TrieNode());
}
node = node.children.get(char);
}
node.isEnd = true;
}
search(word: string): boolean {
let node = this.root;
for (let char of word) {
if (!node.children.has(char)) {
return false;
}
node = node.children.get(char);
}
return node.isEnd;
}
startsWith(prefix: string): boolean {
let node = this.root;
for (let char of prefix) {
if (!node.children.has(char)) {
return false;
}
node = node.children.get(char);
}
return true;
}
}