首页 > 试题广场 >

字典树的实现

[编程题]字典树的实现
  • 热度指数:10876 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
字典树又称为前缀树或者Trie树,是处理字符串常用的数据结构。

假设组成所有单词的字符仅是‘a’~‘z’,请实现字典树的结构,并包含以下四个主要的功能。

1. void insert(String word):添加word,可重复添加;
2. void delete(String word):删除word,如果word添加过多次,仅删除一次;
3. boolean search(String word):查询word是否在字典树中出现过(完整的出现过,前缀式不算);
4. int prefixNumber(String pre):返回以字符串pre作为前缀的单词数量。

现在给定一个m,表示有m次操作,每次操作都为以上四种操作之一。每次操作会给定一个整数op和一个字符串word,op代表一个操作码,如果op为1,则代表添加word,op为2则代表删除word,op为3则代表查询word是否在字典树中,op为4代表返回以word为前缀的单词数量(数据保证不会删除不存在的word)。

对于每次操作,如果op为3时,如果word在字典树中,请输出“YES”,否则输出“NO”;如果op为4时,请输出返回以word为前缀的单词数量,其它情况不输出。
数据范围:操作数满足 ,字符串长度都满足
进阶:所有操作的时间复杂度都满足 
示例1

输入

[["1","qwer"],["1","qwe"],["3","qwer"],["4","q"],["2","qwer"],["3","qwer"],["4","q"]]

输出

["YES","2","NO","1"]

备注:

class TreeNode:
    def __init__(self):
        self.passn = 0
        self.isend = 0
        self.nextn = [None] * 26


class Solution:
    def trieU(self , operators ):
        # write code here
        if operators == []:
            return []
        root = TreeNode()
        res = []
        for opts in operators:
            opt, s = opts
            if opt == '1':
                self.insert(root, s)
            elif opt == '2':
                self.delete(root, s)
            elif opt == '3':
                res.append(self.search(root, s))
            else:
                res.append(self.prefixNumber(root, s))
        return res

    
    def insert(self, root, word):
        sl = len(word)
        i = 0
        while i < sl:
            node = root.nextn[ord(word[i]) - ord('a')]
            if node:
                node.passn += 1
                root = node
            else:
                node = TreeNode()
                node.passn += 1
                root.nextn[ord(word[i]) - ord('a')] = node
                root = node
            i += 1
        root.isend += 1
        
        
    def delete(self, root, word):
        sl = len(word)
        i = 0
        while i < sl:
            node = root.nextn[ord(word[i]) - ord('a')]
            node.passn -= 1
            root = node
            i += 1
        root.isend -= 1
    
    
    def search(self, root, word):
        sl = len(word)
        i = 0
        while i < sl:
            node = root.nextn[ord(word[i]) - ord('a')]
            root = node
            if root == None:
                return 'NO'
            i += 1
        if root != None and root.isend > 0 and i == sl:
            return 'YES'
        else:
            return 'NO'
    
    
    def prefixNumber(self, root, pre):
        sl = len(pre)
        i = 0
        while i < sl:
            node = root.nextn[ord(pre[i]) - ord('a')]
            if node == None:
                break
            root = node
            i += 1
        return root.passn if i == sl else 0

发表于 2021-09-15 15:59:40 回复(0)

使用defaultdict和魔法方法getitemcontains

from collections import defaultdict
class Trie:
    def __init__(self):
        self.chars = defaultdict(Trie)
        self.word_num = 0
        self.pre_num = 0

    def __getitem__(self, k):
        return self.chars[k]

    def __contains__(self, k):
        return k in self.chars

    def insert(self, word):
        cur = self
        for ch in word:
            cur[ch].pre_num += 1
            cur = cur[ch]
        cur.word_num += 1

    def delete(self, word):
        cur = self
        for ch in word:
            cur[ch].pre_num -= 1
            cur = cur[ch]
        cur.word_num -= 1

    def search(self, word):
        cur = self
        for ch in word:
            cur = cur[ch]
        return cur.word_num > 0

    def prefixNumber(self, pre):
        cur = self
        for ch in pre:
            cur = cur[ch]
        return cur.pre_num

class Solution:
    def trieU(self , operators ):
        # write code here
        trie = Trie()
        res = []
        for op, t in operators:
            if op == "1":
                trie.insert(t)
            elif op == "2":
                trie.delete(t)
            elif op == "3":
                res.append("YES" if trie.search(t) else "NO")
            elif op == "4":
                res.append(trie.prefixNumber(t))
        return res
发表于 2021-09-04 18:14:24 回复(1)