【設計】B004_LC_搜索推薦系統(排序 / Trie + count(代辦))

一、Problem

Given an array of strings products and a string searchWord. We want to design a system that suggests at most three product names from products after each character of searchWord is typed. Suggested products should have common prefix with the searchWord. If there are more than three products with a common prefix return the three lexicographically minimums products.

Return list of lists of the suggested products after each character of searchWord is typed.

Input: products = ["mobile","mouse","moneypot","monitor","mousepad"], searchWord = "mouse"
Output: [
["mobile","moneypot","monitor"],
["mobile","moneypot","monitor"],
["mouse","mousepad"],
["mouse","mousepad"],
["mouse","mousepad"]
]
Explanation: products sorted lexicographically = ["mobile","moneypot","monitor","mouse","mousepad"]
After typing m and mo all products match and we show user ["mobile","moneypot","monitor"]
After typing mou, mous and mouse the system suggests ["mouse","mousepad"]

Constraints:

1 <= products.length <= 1000
There are no repeated elements in products.
1 <= Σ products[i].length <= 2 * 10^4
All characters of products[i] are lower-case English letters.
1 <= searchWord.length <= 1000
All characters of searchWord are lower-case English letters.

二、Solution

方法一:排序

題目大意:對於 searchWord,沒輸入一個字符,都要找到與之有相同前綴的產品,如果匹配的產品大於 3 個,那麼取字典序最小的 3 個。

比賽時,這一題我卡在字典序那裏了,原因是我忘記了 qSort 對字符串排序是按照字典序排的,唉;如果按照字典序排序,那麼選出來的字符串就是字典序最小的了。

細節:搜索出來的 “產品們” 可以有重複哦…

class Solution {
    public List<List<String>> suggestedProducts(String[] ps, String sw) {
        Arrays.sort(ps);
        List<List<String>> ans = new LinkedList<>();

        for (int i = 0; i < sw.length(); i++) {
            String pre = sw.substring(0, i+1);
            List<String> l = new LinkedList<>();
            for (String p : ps) if (p.startsWith(pre)) {
                l.add(p);
                if (l.size() == 3)
                    break;
            }
            ans.add(l);
        }
        return ans;
    }
}

Q:如果當前前綴在產品的 [0, i] 範圍內匹配到了(即 list.size() > 0),但在 i+1 位置突然匹配不到了,那麼這個前綴還有必要匹配下去嗎?答案是不需要的,因爲後面的產品名稱都是匹配不上的了。

Q:如果當前前綴 pre 在以 begin 位置爲開頭的匹配區間中匹配不到了,那麼下一個前綴 pre1 肯定比 pre 長吧,那你覺得 pre1 還有可能在 begin 位置及之前匹配到嗎?答案也是不可能的。

基於以上兩個問題,我們可以把程序修改爲以下,然後輕鬆擊敗 99.6%

class Solution {
    public List<List<String>> suggestedProducts(String[] ps, String sw) {
        Arrays.sort(ps);
        List<List<String>> ans = new LinkedList<>();
        int begin = 0;
        
        for (int i = 0; i < sw.length(); i++) {
            String pre = sw.substring(0, i+1);
            List<String> l = new LinkedList<>();
            for (int j = begin; j < ps.length; j++) {
                if (ps[j].startsWith(pre)) {
                    l.add(ps[j]);
                    if (l.size() == 3)
                        break;
                } else {
                    if (l.size() != 0)
                        break;
                    begin++;
                }
            }
            ans.add(l);
        }
        return ans;
    }
}

複雜度分析

  • 時間複雜度:O(n×len2)O(n × len^2),len 爲 searchWord 的長度,n 爲產品總數
  • 空間複雜度:O(...)O(...)

方法二:Trie 樹


複雜度分析

  • 時間複雜度:O()O()
  • 空間複雜度:O()O()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章