【面試高頻題】難度 1/5讳苦,可用 Trie 進(jìn)階的模擬題

題目描述

這是 LeetCode 上的 720. 詞典中最長的單詞 ,難度為 簡(jiǎn)單

Tag : 「模擬」、「哈希表」蚪黑、「字典樹」

給出一個(gè)字符串?dāng)?shù)組 words 組成的一本英語詞典。返回 words 中最長的一個(gè)單詞中剩,該單詞是由 words 詞典中其他單詞逐步添加一個(gè)字母組成。

若其中有多個(gè)可行的答案抒寂,則返回答案中字典序最小的單詞结啼。若無答案,則返回空字符串屈芜。

示例 1:

輸入:words = ["w","wo","wor","worl", "world"]

輸出:"world"

解釋: 單詞"world"可由"w", "wo", "wor", 和 "worl"逐步添加一個(gè)字母組成郊愧。

示例 2:

輸入:words = ["a", "banana", "app", "appl", "ap", "apply", "apple"]

輸出:"apple"

解釋:"apply" 和 "apple" 都能由詞典中的單詞組成朴译。但是 "apple" 的字典序小于 "apply" 

提示:

  • 1 <= words.length <= 1000
  • 1 <= words[i].length <= 30
  • 所有輸入的字符串 words[i] 都只包含小寫字母。

模擬

數(shù)據(jù)范圍很小属铁,我們可以直接模擬來做眠寿。

先將所有的 words[i] 存入 Set 集合,方便后續(xù)可以近似 O(1) 查詢某個(gè)子串是否存在 words 中焦蘑。

遍歷 words 數(shù)組(題目沒有說 words 不重復(fù)盯拱,因此最好遍歷剛剛預(yù)處理的 Set 集合),判斷每個(gè) words[i] 是否為「合法單詞」例嘱,同時(shí)利用當(dāng)前的最長單詞來做剪枝狡逢。

不算剪枝效果,該做法計(jì)算量不超過 10^6拼卵,可以過奢浑。

代碼:

class Solution {
    public String longestWord(String[] words) {
        String ans = "";
        Set<String> set = new HashSet<>();
        for (String s : words) set.add(s);
        for (String s : set) {
            int n = s.length(), m = ans.length();
            if (n < m) continue;
            if (n == m && s.compareTo(ans) > 0) continue;
            boolean ok = true;
            for (int i = 1; i <= n && ok; i++) {
                String sub = s.substring(0, i);
                if (!set.contains(sub)) ok = false;
            }
            if (ok) ans = s;
        }
        return ans;
    }
}
  • 時(shí)間復(fù)雜度:預(yù)處理 Set 集合復(fù)雜度近似 O(n);判斷某個(gè) words[i] 是否合法需要判斷所有子串是否均在 words 中腋腮,復(fù)雜度為 O(m^2)雀彼,其中 m 為字符串長度,處理 words[i] 的過程還使用到 compareTo 操作即寡,其復(fù)雜度為 O(\min(N, M))徊哑,其中 NM 為參與比較的兩字符串長度,該操作相比于生成子串可忽略嘿悬,而對(duì)于一個(gè)長度為 m 的字符串而言实柠,生成其所有的子串的計(jì)算量為首項(xiàng)為 1,末項(xiàng)為 m善涨,公差為 1 的等差數(shù)列求和結(jié)果窒盐。整體復(fù)雜度為 O(\sum_{i = 0}^{n - 1}words[i].length^2)
  • 空間復(fù)雜度:O(\sum_{i = 0}^{n - 1}words[i].length)

Trie

上述解法中「枚舉某個(gè) words[i] 的所有子串,并判斷子串是否在 words 數(shù)組中出現(xiàn)」的操作可使用「字典樹」來實(shí)現(xiàn)钢拧。

不了解「Trie / 字典樹」的同學(xué)可以看前置 ??:字典樹入門蟹漓。里面通過圖例展示了字典樹基本形態(tài),以及提供了「數(shù)組實(shí)現(xiàn)」和「TrieNode 實(shí)現(xiàn)」兩種方式源内,還有「數(shù)組大小估算方式」和「Trie 應(yīng)用面」介紹葡粒。

回到本題,起始先將所有的 words[i] 存入字典樹膜钓,并記錄每個(gè)字符的結(jié)尾編號(hào)嗽交。

對(duì)于某個(gè) words[i] 而言,其能成為「合法單詞」的充要條件為:words[i] 的每個(gè)前綴編號(hào)都有「以結(jié)尾編號(hào)」所被記錄颂斜。

一些細(xì)節(jié):為了防止每個(gè)樣例都 new 大數(shù)組夫壁,我們使用 static 進(jìn)行優(yōu)化,并在跑樣例前進(jìn)行相應(yīng)的清理工作沃疮。

代碼:

class Solution {
    static int N = 30010, M = 26;
    static int[][] tr = new int[N][M];
    static boolean[] isEnd = new boolean[N];
    static int idx = 0;
    void add(String s) {
        int p = 0, n = s.length();
        for (int i = 0; i < n; i++) {
            int u = s.charAt(i) - 'a';
            if (tr[p][u] == 0) tr[p][u] = ++idx;
            p = tr[p][u];
        }
        isEnd[p] = true;
    }
    boolean query(String s) {
        int p = 0, n = s.length();
        for (int i = 0; i < n; i++) {
            int u = s.charAt(i) - 'a';
            p = tr[p][u];
            if (!isEnd[p]) return false;
        }
        return true;
    }
    public String longestWord(String[] words) {
        Arrays.fill(isEnd, false);
        for (int i = 0; i <= idx; i++) Arrays.fill(tr[i], 0);
        idx = 0;

        String ans = "";
        for (String s : words) add(s);
        for (String s : words) {
            int n = s.length(), m = ans.length();
            if (n < m) continue;
            if (n == m && s.compareTo(ans) > 0) continue;
            if (query(s)) ans = s;
        }
        return ans;
    }
}
  • 時(shí)間復(fù)雜度:將所有 words[i] 存入字典樹的復(fù)雜度為 O(\sum_{i = 0}^{n - 1}words[i].length)盒让;查詢每個(gè) words[i] 是否合法的復(fù)雜度為 O(m)梅肤,其中 m 為當(dāng)前 words[i] 長度。整體復(fù)雜度為 O(\sum_{i = 0}^{n - 1}words[i].length)
  • 空間復(fù)雜度:O(C)

最后

這是我們「刷穿 LeetCode」系列文章的第 No.720 篇邑茄,系列開始于 2021/01/01姨蝴,截止于起始日 LeetCode 上共有 1916 道題目,部分是有鎖題肺缕,我們將先把所有不帶鎖的題目刷完左医。

在這個(gè)系列文章里面,除了講解解題思路以外搓谆,還會(huì)盡可能給出最為簡(jiǎn)潔的代碼炒辉。如果涉及通解還會(huì)相應(yīng)的代碼模板。

為了方便各位同學(xué)能夠電腦上進(jìn)行調(diào)試和提交代碼泉手,我建立了相關(guān)的倉庫:https://github.com/SharingSource/LogicStack-LeetCode 黔寇。

在倉庫地址里,你可以看到系列文章的題解鏈接斩萌、系列文章的相應(yīng)代碼缝裤、LeetCode 原題鏈接和其他優(yōu)選題解。

更多更全更熱門的「筆試/面試」相關(guān)資料可訪問排版精美的 合集新基地 ????

本文由mdnice多平臺(tái)發(fā)布

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末颊郎,一起剝皮案震驚了整個(gè)濱河市憋飞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌姆吭,老刑警劉巖榛做,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異内狸,居然都是意外死亡检眯,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門昆淡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锰瘸,“玉大人,你說我怎么就攤上這事昂灵”苣” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵眨补,是天一觀的道長管削。 經(jīng)常有香客問我,道長撑螺,這世上最難降的妖魔是什么含思? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮实蓬,結(jié)果婚禮上茸俭,老公的妹妹穿的比我還像新娘。我一直安慰自己安皱,他們只是感情好调鬓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著酌伊,像睡著了一般腾窝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上居砖,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天虹脯,我揣著相機(jī)與錄音,去河邊找鬼奏候。 笑死循集,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蔗草。 我是一名探鬼主播咒彤,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼咒精!你這毒婦竟也來了镶柱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤模叙,失蹤者是張志新(化名)和其女友劉穎歇拆,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體范咨,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡故觅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了湖蜕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逻卖。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖昭抒,靈堂內(nèi)的尸體忽然破棺而出评也,到底是詐尸還是另有隱情,我是刑警寧澤灭返,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布盗迟,位于F島的核電站,受9級(jí)特大地震影響熙含,放射性物質(zhì)發(fā)生泄漏罚缕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一怎静、第九天 我趴在偏房一處隱蔽的房頂上張望邮弹。 院中可真熱鬧黔衡,春花似錦、人聲如沸腌乡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽与纽。三九已至侣签,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間急迂,已是汗流浹背影所。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留僚碎,地道東北人猴娩。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像听盖,于是被迫代替她去往敵國和親胀溺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容