Featured image of post Search Suggestions System

Search Suggestions System

1268. 搜索推荐系统

分析

  1. 排序产品数组

    • 为了能够快速按字典序找到前缀匹配的产品,首先对 products 按字典序排序
  2. 前缀匹配

    • searchWord 的每个前缀:
      • 使用一个变量 cur 保存当前前缀(即累加输入的字母)
      • 使用一个指针 k 维护当前搜索范围的起点。对于排序后的数组,可以跳过所有小于 cur 的字符串,加速搜索。
      • 遍历从 k 开始的最多三个字符串,检查它们是否以 cur 为前缀,若满足条件则加入推荐结果
  3. 提前结束

    • 对于排序后的数组,如果某个字符串不再满足当前前缀条件,后续的字符串也不可能满足,可以提前结束内层循环

时间复杂度

  • 排序:O(mlogm),其中 mproducts 的长度
  • 前缀匹配:对于 searchWord 的每个字符,我们最多遍历 products 中 3 个字符串,复杂度为 O(n * avgLen),其中 nsearchWord 的长度,avgLen 是产品的平均长度

总复杂度:O(mlogm + n * avgLen

空间复杂度

空间复杂度为 O(n)

C++代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Solution
{
public:
    vector<vector<string>> suggestedProducts(vector<string>& products, string searchWord)
    {
        // 结果数组
        std::vector<std::vector<std::string>> res;

        // 按字典序排序产品数组
        std::sort(products.begin(), products.end());

        // 当前前缀和产品数组的起点指针
        std::string cur;
        int n = products.size(), k = 0;

        // 遍历 searchWord 的每个字母
        for (char c : searchWord)
        {
            cur += c; // 更新当前前缀

            // 移动指针 k 跳过所有小于当前前缀的字符串
            while (k < n && products[k] < cur)
                ++k;

            // 收集符合条件的最多三个产品
            std::vector<std::string> tmp;
            for (int i = k; i < n && i < k + 3; ++i)
            {
                // 判断当前字符串是否以 cur 为前缀
                if (products[i].substr(0, cur.size()) == cur)
                    tmp.push_back(products[i]);
                else
                    break; // 剪枝:后续字符串不会匹配,提前退出
            }

            // 将当前前缀的推荐结果加入结果数组
            res.push_back(tmp);
        }
        return res;
    }
};
Built with Hugo
Theme Stack designed by Jimmy