【Leetcode】648. Replace Words

題目地址:

https://leetcode.com/problems/replace-words/

給定一個字符串數組,再給定一個英文句子,句子裏只含英文單詞,並且以空格分隔。如果句子中的某個單詞以數組中某個字符串爲前綴,則將其替換爲這個前綴。存在多個字符串作爲其前綴,則取最短的那個。返回替換完後的英文句子。

思路是用Trie,將數組中所有字符串存進一個Trie中,然後將英文句子分割成單詞,對每個單詞尋找Trie中的最短前綴即可。代碼如下:

import java.util.List;

public class Solution {
    class Trie {
        class Node {
            boolean isWord;
            Node[] next;
            Node() {
                next = new Node[26];
            }
        }
        
        Node root;
        
        Trie(List<String> dict) {
            root = new Node();
            for (String word : dict) {
                insert(word);
            }
        }
        
        // 這裏的insert的時候,如果發現走到了單詞末尾就直接退出,不需要繼續添加了,
        // 原因是題目只要求找最短前綴,如果兩個字符串一個是另一個的前綴,那只需要存短的那個就行了
        private void insert(String word) {
            Node cur = root;
            for (int i = 0; i < word.length(); i++) {
                char c = word.charAt(i);
                if (cur.next[c - 'a'] == null) {
                    cur.next[c - 'a'] = new Node();
                }
                cur = cur.next[c - 'a'];
                // 遇到單詞末尾了直接退出
                if (cur.isWord) {
                    return;
                }
            }
            
            cur.isWord = true;
        }
        // 在Trie裏尋找word的最短前綴,並這個最短前綴返回;若不存在則返回空串
        private String prefixOf(String word) {
            StringBuilder sb = new StringBuilder();
            Node cur = root;
            for (int i = 0; i < word.length(); i++) {
                char c = word.charAt(i);
                if (cur.next[c - 'a'] != null) {
                	// 每走一步就append路徑上的字符
                    cur = cur.next[c - 'a'];
                    sb.append(c);
                } else {
                	// 走到null說明Trie裏不存在word的前綴,直接跳出返回空串
                    break;
                }
                // 如果第一次發現了單詞末尾,那麼就找到了最短前綴,直接返回前綴
                if (cur.isWord) {
                    return sb.toString();
                }
            }
            
            return "";
        }
    }
    
    
    public String replaceWords(List<String> dict, String sentence) {
        Trie trie = new Trie(dict);
        String[] words = sentence.split(" ");
    
        for (int i = 0; i < words.length; i++) {
            String word = words[i];
            // 找word的在trie中的最短前綴
            String pref = trie.prefixOf(word);
            // 如果pref爲空,那說明不存在前綴,跳過該單詞;否則進行替換
            if (!pref.isEmpty()) {
                words[i] = pref;
            }
        }
    	// 最後以空格join回來
        return String.join(" ", words);
    }
}

時空複雜度O(n)O(n)nn爲句子的長度。

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