【设计】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 × l e n 2 ) O(n × len^2) O(n×len2),len 为 searchWord 的长度,n 为产品总数
  • 空间复杂度: O ( . . . ) O(...) O(...)

方法二:Trie 树


复杂度分析

  • 时间复杂度: O ( ) O() O()
  • 空间复杂度: O ( ) O() O()

你可能感兴趣的:(#,前缀树,#,【设计】)