442-实现 Trie

实现一个 Trie,包含 insert, search, 和 startsWith 这三个方法。

注意事项

你可以假设所有的输入都是小写字母a-z。

样例

insert("lintcode")

search("code") // return false

startsWith("lint") // return true

startsWith("linterror") // return false

insert("linterror")

search("lintcode) // return true

startsWith("linterror") // return true

标签

字典树 脸书 谷歌 优步

思路

字典树(Trie)可以保存一些 字符串->值 的对应关系。基本上,它跟 Java 的 HashMap 功能相同,都是 key-value 映射,只不过 Trie 的 key 只能是字符串。

Trie 的强大之处就在于它的时间复杂度。它的插入和查询时间复杂度都为 O(k) ,其中 k 为 key 的长度,与 Trie 中保存了多少个元素无关。Hash 表号称是 O(1) 的,但在计算 hash 的时候就肯定会是 O(k) ,而且还有碰撞之类的问题;Trie 的缺点是空间消耗很高。

Trie树的基本性质可以归纳为:

  1. 根节点不包含字符,除根节点意外每个节点只包含一个字符。
  2. 从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。
  3. 每个节点的所有子节点包含的字符串不相同。

Trie树有一些特性:

  1. 根节点不包含字符,除根节点外每一个节点都只包含一个字符。
  2. 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
  3. 每个节点的所有子节点包含的字符都不相同。
  4. 如果字符的种数为n,则每个结点的出度为n,这也是空间换时间的体现,浪费了很多的空间。
  5. 插入查找的复杂度为O(n),n为字符串长度。

基本思想(以字母树为例):

1、插入过程

对于一个单词,从根开始,沿着单词的各个字母所对应的树中的节点分支向下走,直到单词遍历完,将最后的节点标记为红色,表示该单词已插入Trie树。

2、查询过程

同样的,从根开始按照单词的字母顺序向下遍历trie树,一旦发现某个节点标记不存在或者单词遍历完成而最后的节点未标记为红色,则表示该单词不存在,若最后的节点标记为红色,表示该单词存在。

code

/**
* Your Trie object will be instantiated and called as such:
* Trie trie;
* trie.insert("lintcode");
* trie.search("lint"); will return false
* trie.startsWith("lint"); will return true
*/
class TrieNode {
public:
// Initialize your data structure here.
char c;
TrieNode * next[26];
bool isEnd; TrieNode() {
c = ' ';
for (int i = 0; i < 26; i++) {
next[i] = nullptr;
}
isEnd = false;
} TrieNode(char c) {
this->c = c;
for (int i = 0; i < 26; i++) {
next[i] = nullptr;
}
isEnd = false;
}
}; class Trie {
public:
Trie() {
root = new TrieNode();
} // Inserts a word into the trie.
void insert(string word) {
TrieNode* curNode = root;
for (int i = 0; i < word.size(); i++) {
if (curNode->next[word[i] - 'a'] != nullptr) {
curNode = curNode->next[word[i] - 'a'];
}
else {
TrieNode* node = new TrieNode(word[i]);
curNode->next[word[i] - 'a'] = node;
curNode = node;
}
}
curNode->isEnd = true;
} // Returns if the word is in the trie.
bool search(string word) {
TrieNode* curNode = root;
for (int i = 0; i < word.size(); i++) {
if (curNode->next[word[i] - 'a'] == nullptr) {
return false;
}
else {
curNode = curNode->next[word[i] - 'a'];
}
}
return curNode->isEnd;
} // Returns if there is any word in the trie
// that starts with the given prefix.
bool startsWith(string prefix) {
TrieNode* curNode = root;
for (int i = 0; i < prefix.size(); i++) {
if (curNode->next[prefix[i] - 'a'] == nullptr) {
return false;
}
else {
curNode = curNode->next[prefix[i] - 'a'];
}
}
return true;
} private:
TrieNode* root;
};

lintcode-442-实现 Trie的更多相关文章

  1. [LintCode]——目录

    Yet Another Source Code for LintCode Current Status : 232AC / 289ALL in Language C++, Up to date (20 ...

  2. Trie - 20181113

    442. Implement Trie (Prefix Tree) class TrieNode { public boolean isWord; public TrieNode[] children ...

  3. [LintCode] Implement Trie 实现字典树

    Implement a trie with insert, search, and startsWith methods. Have you met this question in a real i ...

  4. lintcode 中等题: Implement Trie

    题目 Implement Trie Implement a trie with insert, search, and startsWith methods. 样例   注意 You may assu ...

  5. Implement Trie(LintCode)

    Implement Trie Implement a trie with insert, search, and startsWith methods. 样例   注意 You may assume ...

  6. [leetcode/lintcode 题解] 微软 面试题:实现 Trie(前缀树)

    实现一个 Trie,包含 ​insert​, ​search​, 和 ​startsWith​ 这三个方法.   在线评测地址:领扣题库官网     样例 1: 输入:    insert(" ...

  7. Implement Trie (Prefix Tree) 解答

    Question Implement a trie with insert, search, and startsWith methods. Note:You may assume that all ...

  8. leetcode & lintcode for bug-free

    刷题备忘录,for bug-free leetcode 396. Rotate Function 题意: Given an array of integers A and let n to be it ...

  9. leetcode & lintcode 题解

    刷题备忘录,for bug-free 招行面试题--求无序数组最长连续序列的长度,这里连续指的是值连续--间隔为1,并不是数值的位置连续 问题: 给出一个未排序的整数数组,找出最长的连续元素序列的长度 ...

随机推荐

  1. 一图看懂Kafka On Zookeeper

    Kafka On Zookeeper,点击看大图

  2. 用函数指针将字符串 ”hello world“ 输出为 "world hello”

    /************************************************************************* > File Name: 指针数组2.c & ...

  3. [Golang学习笔记] 05 程序实体2 作用域访问权限和变量重声明

    作用域访问权限: 程序实体访问权限(作用域)有三种:1. 包级私有(代码包)2. 模块级私有(代码包)3. 公开(全域). 一个函数是一个代码块.一个程序实体的作用域总是会被限制在某个代码块中.好处: ...

  4. rcosfir函数的用法

    B = rcosfir(R, N_T, RATE, T, FILTER_TYPE) designs and returns a square root raised cosine filter if ...

  5. 20155234 2610-2017-2第九周《Java学习笔记》学习总结

    20155234第九周<Java学习笔记>学习总结 教材学习内容总结 数据库本身是个独立运行的应用程序 撰写应用程序是利用通信协议对数据库进行指令交换,以进行数据的增删查找 JDBC(Ja ...

  6. C语言学习笔记1

    C语言假期学习笔记1 关于吃回车问题 第一个解决方案是使用ch=getchar(); 第二个方案是在scanf(" %c",&b):在%c加空格,将存于缓冲区的回车符读入 ...

  7. python中快速获取本地时区当天0点时间戳的一种方法

    如下所示,看了网上的几种方法,这种方法算是代码量比较小的,同时可以保证求的是本地时区的0点时间戳,返回的是浮点数,需要的话自己转一下int In [1]: import time In [2]: fr ...

  8. 【转载】OGRE中用到的设计模式

    原文:OGRE中用到的设计模式 1.       单例模式(Singleton) 2.       工厂方法(Factory Method)  3.       适配器模式(Adapter)  4.  ...

  9. Linux 删除用户时报错:userdel: user zhoulijiang is currently used by process 1

    一.发现问题: 有技术人员离职,需要删除系统帐号,但是进行删除操作的时候报:" userdel: user zhoulijiang is currently used by process ...

  10. idea alt+enter导包时被锁定导某一个包时的解决方法

    在只有一个包指向的时候,把光标放在Test这种字符之间的话 就会直接导这个 所以把光标放在最后就可以导别的了