208. 实现 Trie (前缀树)
实现一个 Trie (前缀树),包含
insert
,search
, 和startsWith
这三个操作。示例:
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
说明:
- 你可以假设所有的输入都是由小写字母
a-z
构成的。- 保证所有输入均为非空字符串。
class Trie {
private class Node{
public boolean isWord; //记录该Node是不是一个字符串的结尾
public TreeMap<Character, Node> next; //该Node的下一个Node的Map
public Node(boolean isWord){
this.isWord = isWord;
this.next = new TreeMap<>();
}
public Node(){
this(false);
}
}
private Node root;
/** Initialize your data structure here. */
public Trie() {
root = new Node();
}
/** Inserts a word into the trie. */
public void insert(String word) {
Node cur = root;
for (int i=0; i<word.length(); i++){
char c = word.charAt(i);
//判断当前Node的子节点中是否存在值为c的节点
if(cur.next.get(c) == null){
cur.next.put(c, new Node());
}
//指针后移
cur = cur.next.get(c);
}
//注意,这里为了防止对重复字符串进行计数,需要做一个if判断
if(!cur.isWord){
cur.isWord = true;
}
}
/** Returns if the word is in the trie. */
public boolean search(String word) {
Node cur = root;
for(int i = 0; i<word.length(); i++){
char c = word.charAt(i);
if(cur.next.get(c)==null){
return false;
}
//指针后移
cur = cur.next.get(c);
}
return cur.isWord;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
public boolean startsWith(String prefix) {
Node cur = root;
for(int i = 0; i<prefix.length(); i++){
char c = prefix.charAt(i);
if(cur.next.get(c) == null){
return false;
}
cur = cur.next.get(c);
}
return true;
}
}
/**
* Your Trie object will be instantiated and called as such:
* Trie obj = new Trie();
* obj.insert(word);
* boolean param_2 = obj.search(word);
* boolean param_3 = obj.startsWith(prefix);
*/
211. 添加与搜索单词 - 数据结构设计
设计一个支持以下两种操作的数据结构:
void addWord(word) bool search(word)
search(word) 可以搜索文字或正则表达式字符串,字符串只包含字母
.
或a-z
。.
可以表示任何一个字母。示例:
addWord("bad") addWord("dad") addWord("mad") search("pad") -> false search("bad") -> true search(".ad") -> true search("b..") -> true
说明:
你可以假设所有单词都是由小写字母
a-z
组成的。
思路:这是一个字符串的模式匹配问题
class WordDictionary {
private class Node{
public boolean isWord;
TreeMap<Character, Node> next;
public Node(){
this.isWord = false;
this.next = new TreeMap<>();
}
}
private Node root;
/** Initialize your data structure here. */
public WordDictionary() {
this.root = new Node();
}
/** Adds a word into the data structure. */
public void addWord(String word) {
Node cur = root;
for(int i=0; i<word.length(); i++){
char c = word.charAt(i);
if(cur.next.get(c) == null){
cur.next.put(c, new Node());
}
cur = cur.next.get(c);
}
if(!cur.isWord){
cur.isWord = true;
}
}
/** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
public boolean search(String word) {
if(word.length()>0){
return search(root, word, 0);
}
return false;
}
private boolean search(Node node, String word, int index){
//递归退出条件
if(index == word.length()){
return node.isWord;
}
char c = word.charAt(index);
if(c!='.'){
if(node.next.get(c)!=null){
return search(node.next.get(c), word, index+1); //需要return???
}
return false;
}else{
for(char key: node.next.keySet()){
//只判断可不可以匹配,不需要计算有多少个相匹配的,所以只要找到一个匹配的就可以返回true
if(search(node.next.get(key), word, index+1)){
return true;
}
}
return false;
}
}
}
/**
* Your WordDictionary object will be instantiated and called as such:
* WordDictionary obj = new WordDictionary();
* obj.addWord(word);
* boolean param_2 = obj.search(word);
*/
677. 键值映射
实现一个 MapSum 类里的两个方法,
insert
和sum
。对于方法
insert
,你将得到一对(字符串,整数)的键值对。字符串表示键,整数表示值。如果键已经存在,那么原来的键值对将被替代成新的键值对。对于方法
sum
,你将得到一个表示前缀的字符串,你需要返回所有以该前缀开头的键的值的总和。示例 1:
输入: insert("apple", 3), 输出: Null 输入: sum("ap"), 输出: 3 输入: insert("app", 2), 输出: Null 输入: sum("ap"), 输出: 5
思路:这是一个字符串映射问题,可以通过维护Trie节点内的值来完成
class MapSum {
private class Node{
public int val;
public TreeMap<Character, Node> next;
public Node(){
this.val = 0;
next = new TreeMap<>();
}
}
private Node root;
/** Initialize your data structure here. */
public MapSum() {
root = new Node();
}
public void insert(String key, int val) {
Node cur = root;
for(int i=0; i<key.length();i++){
char c = key.charAt(i);
if(cur.next.get(c)==null){
cur.next.put(c, new Node());
}
cur = cur.next.get(c);
}
cur.val = val;
}
public int sum(String prefix) {
Node cur = root;
for(int i=0; i<prefix.length();i++){
char c = prefix.charAt(i);
if(cur.next.get(c)==null){
return 0;
}
cur = cur.next.get(c);
}
return sum(cur);
}
private int sum(Node node){
//递归退出条件,可以省略 因为node.next.size()==0时,下面的循环不会进行
if(node.next.size()==0){
return node.val;
}
int sum = node.val;
for(char key : node.next.keySet()){
sum = sum+sum(node.next.get(key));
}
return sum;
}
}
/**
* Your MapSum object will be instantiated and called as such:
* MapSum obj = new MapSum();
* obj.insert(key,val);
* int param_2 = obj.sum(prefix);
*/