目录
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 。示例:
输入
[“Trie”, “insert”, “search”, “search”, “startsWith”, “insert”, “search”]
[[], [“apple”], [“apple”], [“app”], [“app”], [“app”], [“app”]]
输出
[null, null, true, false, true, null, true]解释
Trie trie = new Trie();
trie.insert(“apple”);
trie.search(“apple”); // 返回 True
trie.search(“app”); // 返回 False
trie.startsWith(“app”); // 返回 True
trie.insert(“app”);
trie.search(“app”); // 返回 True
type Trie struct {
isEnd bool
children [26]*Trie
}
func Constructor() Trie {
return Trie{}
}
func (this *Trie) Insert(word string) {
t := this
for _, c := range word {
idx := c - 'a'
if t.children[idx] == nil {
t.children[idx] = &Trie{}
}
t = t.children[idx]
}
t.isEnd = true
}
func (this *Trie) Search(word string) bool {
node := this
for _, c := range word {
idx := c - 'a'
if node.children[idx] == nil {
return false
}
node = node.children[idx]
}
return node.isEnd
}
func (this *Trie) StartsWith(prefix string) bool {
node := this
for _, c := range prefix {
idx := c - 'a'
if node.children[idx] == nil {
return false
}
node = node.children[idx]
}
return true
}
677. 键值映射
设计一个 map ,满足以下几点:
字符串表示键,整数表示值
返回具有前缀等于给定字符串的键的值的总和
实现一个 MapSum 类:MapSum() 初始化 MapSum 对象
void insert(String key, int val) 插入 key-val 键值对,字符串表示键 key ,整数表示值 val 。如果键 key 已经存在,那么原来的键值对 key-value 将被替代成新的键值对。
int sum(string prefix) 返回所有以该前缀 prefix 开头的键 key 的值的总和。示例 1:
输入:
[“MapSum”, “insert”, “sum”, “insert”, “sum”]
[[], [“apple”, 3], [“ap”], [“app”, 2], [“ap”]]
输出:
[null, null, 3, null, 5]解释:
MapSum mapSum = new MapSum();
mapSum.insert(“apple”, 3);
mapSum.sum(“ap”); // 返回 3 (apple = 3)
mapSum.insert(“app”, 2);
mapSum.sum(“ap”); // 返回 5 (apple + app = 3 + 2 = 5)
如果键 key 已经存在,那么原来的键值对 key-value 将被替代成新的键值对。这里使用map记录每次插入的记录,这里使用了delta技巧
type MapSum struct {
cnt map[string]int
root *Trie
}
type Trie struct {
children [26]*Trie
val int
}
func Constructor() MapSum {
return MapSum{map[string]int{}, &Trie{}}
}
func (this *MapSum) Insert(key string, val int) {
node := this.root
delta := val
if this.cnt[key] > 0 {
delta -= this.cnt[key]
}
this.cnt[key] = val
for _, c := range key {
idx := c - 'a'
if node.children[idx] == nil {
node.children[idx] = &Trie{}
}
node.children[idx].val += delta
node = node.children[idx]
}
}
func (this *MapSum) Sum(prefix string) int {
node := this.root
for _, c := range prefix {
idx := c - 'a'
if node.children[idx] == nil {
return 0
}
node = node.children[idx]
}
return node.val
}
211. 添加与搜索单词 - 数据结构设计
请你设计一个数据结构,支持 添加新单词 和 查找字符串是否与任何先前添加的字符串匹配 。
实现词典类 WordDictionary :
WordDictionary() 初始化词典对象
void addWord(word) 将 word 添加到数据结构中,之后可以对它进行匹配
bool search(word) 如果数据结构中存在字符串与 word 匹配,则返回 true ;否则,返回 false 。word 中可能包含一些 ‘.’ ,每个 . 都可以表示任何一个字母。示例:
输入:
[“WordDictionary”,“addWord”,“addWord”,“addWord”,“search”,“search”,“search”,“search”]
[[],[“bad”],[“dad”],[“mad”],[“pad”],[“bad”],[“.ad”],[“b…”]]
输出:
[null,null,null,null,false,true,true,true]解释:
WordDictionary wordDictionary = new WordDictionary();
wordDictionary.addWord(“bad”);
wordDictionary.addWord(“dad”);
wordDictionary.addWord(“mad”);
wordDictionary.search(“pad”); // 返回 False
wordDictionary.search(“bad”); // 返回 True
wordDictionary.search(“.ad”); // 返回 True
wordDictionary.search(“b…”); // 返回 True
处理search的方法位深度优先搜索
type WordDictionary struct {
root *Trie
}
func Constructor() WordDictionary {
return WordDictionary{&Trie{}}
}
func (this *WordDictionary) AddWord(word string) {
this.root.Insert(word)
}
func (this *WordDictionary) Search(word string) bool {
return dfs(word, 0, this.root)
}
func dfs(word string, idx int,node *Trie) bool {
if len(word) == idx {
return node.isEnd
}
ch := word[idx]
if ch == '.' {
for i := 0; i < 26; i++ {
child := node.children[i]
if child != nil && dfs(word, idx+1, child) {
return true
}
}
} else {
child := node.children[ch-'a']
return child != nil && dfs(word, idx+1, child)
}
return false
}
type Trie struct {
isEnd bool
children [26]*Trie
}
func(t *Trie)Insert(word string) {
node := t
for _, c := range word {
idx := c - 'a'
if node.children[idx] == nil {
node.children[idx] = &Trie{}
}
node = node.children[idx]
}
node.isEnd = true
}
648. 单词替换
在英语中,我们有一个叫做 词根(root) 的概念,可以词根后面添加其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如,词根an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。
现在,给定一个由许多词根组成的词典 dictionary 和一个用空格分隔单词形成的句子 sentence。你需要将句子中的所有继承词用词根替换掉。如果继承词有许多可以形成它的词根,则用最短的词根替换它。
你需要输出替换之后的句子。
示例 1:
输入:dictionary = [“cat”,“bat”,“rat”], sentence = “the cattle was rattled by the battery”
输出:“the cat was rat by the bat”
示例 2:输入:dictionary = [“a”,“b”,“c”], sentence = “aadsfasf absbs bbab cadsfafs”
输出:“a a b c”
func replaceWords(dictionary []string, sentence string) string {
strArray := strings.Fields(sentence)
trie := New()
for _, word := range dictionary {
trie.Insert(word)
}
ans := trie.Prefix(strArray[0])
for i := 1; i < len(strArray); i++ {
ans += " " + trie.Prefix(strArray[i])
}
return ans
}
type Trie struct {
isEnd bool
children [26]*Trie
}
func New() Trie {
return Trie{}
}
func (t *Trie) Insert(word string) {
node := t
for _, c := range word {
idx := c - 'a'
if node.children[idx] == nil {
node.children[idx] = &Trie{}
}
node = node.children[idx]
}
node.isEnd = true
}
func (t *Trie) Prefix(word string) string {
ans := ""
node := t
for _, c := range word {
idx := c - 'a'
if node.isEnd {
return ans
}
if node.children[idx] == nil {
return word
}
node = node.children[idx]
ans += string('a' + idx)
}
return word
}