leetcode 前缀树

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
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值