본문 바로가기

내 맘대로 알고리즘/LeetCode 2020 May

May LeetCoding Challenge[Day14] - Implement Trie (Prefix Tree)

Implement a trie with insert, search, and startsWith methods.

Note:
You may assume that all inputs are consist of lowercase letters a-z.All inputs are guaranteed to be non-empty strings.
Trie trie = new Trie();
trie.insert("apple");
trie.search("apple"); // returns true
trie.search("app"); // returns false
trie.startsWith("app"); // returns true
trie.insert("app");
trie.search("app"); // returns true

1. 알고리즘을 해결하기 위해서 생각한 방법

 

 - Trie라는 구조를 모르고 있었고, 해당 문제를 해결하기 위해서, LeetCode에서 제공하는 솔루션을 공부했습니다.

 - Trie는 문자열을 저장하고, 특정 문자열이 존재하는 지, 빠르게 검색할 수 있는 자료구조입니다.

 - 해당 문제에서는 insert, search, startsWith를 구현합니다.

 

2. 알고리즘 작성 중, 어려운 점

 

- 해당 문제를 어떤 자료구조로 접근해야할까?

 

3. 내가 작성한 알고리즘

 

class Trie {
    Node root;
    class Node{
        Node[] node = new Node['z'-'a' + 1];
        boolean isEnd = false;
        
    }
    /** Initialize your data structure here. */
    public Trie() {
        root = new Node();
    }
    
    /** Inserts a word into the trie. */
    public void insert(String word) {
        Node tmp = root;
        for(int i=0; i<word.length(); i++){
            if(tmp.node['z' - word.charAt(i)] == null){
                tmp.node['z' - word.charAt(i)] = new Node();
            }
            tmp = tmp.node['z' - word.charAt(i)];
        }
        tmp.isEnd = true;
    }
    
    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        Node tmp = root;
        for(int i=0; i<word.length(); i++){
            if(tmp.node['z' - word.charAt(i)] == null){
                return false;
            }
            tmp = tmp.node['z' - word.charAt(i)];
        }
        return tmp.isEnd;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        Node tmp = root;
        for(int i=0; i<prefix.length(); i++){
            if(tmp.node['z' - prefix.charAt(i)] == null){
                return false;
            }
            tmp = tmp.node['z' - prefix.charAt(i)];
        }
        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);
 */

 

4. 알고리즘을 보고, 공부한 내용

 

 - Insert : root 노드에 a-z까지의 소문자 배열을 갖고 있을 때, 각 배열에 소문자만큼의 노드를 갖고 추가해준다.

 공간복잡도는 소문자의 길이 25 * 문자열의 길이만큼 추가되는 것 같다.

  예제에서는 abc, apple, apk를 추가하는데, abc인 경우, 'a'를 만들고, 노드를 만들고, 'b'를 만들고, 노드를 만들고, 'c'를 만들고, 노드를 만든다. 마지막에는 isEnd로 해서 더 이상 검색할 내용을 알려준다.

 따라서, 노드가 갖고 있는 정보는 Node[26] child 와 boolean isEnd 의 정보를 가져야 한다.

 

 - Search : app를 검색하는 예제이다. apple이 이에 매칭이 되는데, Node.child['a'] -> Node.child['a'].child['p'] ->

Node.child['a'].child['p'].child['p']로 간다. search일 때는, isEnd 값을 확인하는데 apple은 Node.child['a'].child['p'].child['p'].child['l'].child['e']가 isEnd가 true 이므로, 해당 search 결과는 false가 return 된다.

 

- startWith : app을 검색하는 똑같은 예제일 때, startWith는 search와 동일 과정을 거치고, 마지막에 isEnd를 검사하지 않으므로, 무조건 return true를 한다.

 

 

5. 결과

 

문제 : https://leetcode.com/explore/challenge/card/may-leetcoding-challenge/535/week-2-may-8th-may-14th/3329/

 

Explore - LeetCode

LeetCode Explore is the best place for everyone to start practicing and learning on LeetCode. No matter if you are a beginner or a master, there are always new topics waiting for you to explore.

leetcode.com