LeetCode——208. 實現 Trie (前綴樹)

208. 實現 Trie (前綴樹)

定義

又稱單詞查找樹,Trie樹,是一種樹形結構,是一種哈希樹的變種。典型應用是用於統計,排序和保存大量的字符串(但不僅限於字符串),所以經常被搜索引擎系統用於文本詞頻統計。它的優點是:利用字符串的公共前綴來減少查詢時間,最大限度地減少無謂的字符串比較,查詢效率比哈希樹高。
在這裏插入圖片描述
例如:
Trie存儲的是單詞,查詢的時間複雜度是O(w),w爲所查詢單詞的長度;如果使用樹結構進行存儲,查詢的時間複雜度爲O(logn);當存儲的單詞數量逐漸增多的情況下,樹結構查詢的時間複雜度是逐漸大於Trie的,而Trie的時間複雜度還是O(w),不會因爲存儲單詞的多少而發生變化。

侷限性

class Node{
public boolean isWord;// 是否爲單詞結尾
public TreeMap<Character, Node> next;// 存儲節點和字母  使用映射連接每個節點
}

最大的問題是空間!原本存儲一個單詞使用一個節點的空間,現在每個節點只能存儲一個字母,相比之前空間佔用成倍上升,解決方法詳見壓縮字典樹Compressed 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 構成的。
保證所有輸入均爲非空字符串。

Trie.java(字典樹)

import java.util.TreeMap;

//字典樹Trie
public class Trie {

	private class Node {
		public boolean isWord;// 是否爲單詞結尾
		public TreeMap<Character, Node> next;// 存儲節點和字母  使用映射連接每個節點

		public Node(boolean isWord) {
			this.isWord = isWord;
			next = new TreeMap<>();
		}

		public Node() {
			// TODO Auto-generated constructor stub
			this(false);
		}
	}

	private Node root;// 根結點
	private int size;// 存儲單詞個數

	public Trie() {
		// TODO Auto-generated constructor stub
		root = new Node();
		size = 0;
	}

	public int getSize() {
		return size;
	}

	// 添加一個新的單詞
	public void insert(String word) {
		Node cur = root;
		for (int i = 0; i < word.length(); i++) {// 遍歷單詞的字符
			char c = word.charAt(i);
			if (cur.next.get(c) == null)// 是否已經包含字符c
				cur.next.put(c, new Node());// 添加
			cur = cur.next.get(c);// 如果有,cur指向c
		}
		if (!cur.isWord) {// 如果這個單詞之前沒有
			cur.isWord = true;// 單詞結束
			size++;
		}
	}

	// 查詢Trie中是否有單詞word
	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;// 判斷cur.isWord是否爲true
	}

	// 查詢Trie中是否存在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;
	}
}

Main.java(測試)

public class Main {
	public static void main(String[] args) {
		Trie t = new Trie();
		Trie trie = new Trie();
		trie.insert("apple");
		System.out.println(trie.search("apple"));  // 返回 true
		System.out.println(trie.search("app"));     // 返回 false
		System.out.println(trie.startsWith("app")); // 返回 true
		trie.insert("app");   
		System.out.println(trie.search("app")  );   // 返回 true
	}
}

測試結果
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章