leetcode
leetcode 1201 ~ 1250
搜索推荐系统

搜索推荐系统

难度:

标签:

题目描述

代码结果

运行时间: 40 ms, 内存: 18.9 MB


/*
  思路:
  1. 使用Java Stream对产品列表进行字典序排序。
  2. 对搜索词的每个前缀,使用Stream过滤并获取前三个匹配的产品。
*/
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Solution {
    public List<List<String>> suggestedProducts(String[] products, String searchWord) {
        Arrays.sort(products);
        List<List<String>> result = new ArrayList<>();
        for (int i = 0; i < searchWord.length(); i++) {
            String prefix = searchWord.substring(0, i + 1);
            List<String> suggestions = Arrays.stream(products)
                .filter(product -> product.startsWith(prefix))
                .limit(3)
                .collect(Collectors.toList());
            result.add(suggestions);
        }
        return result;
    }
}

解释

方法:

该题解采用最小堆的方法来维护字典序的顺序,首先将所有的产品放入最小堆中。然后,对于搜索词的每个字符,它会遍历最小堆,检查堆顶元素的前缀是否与搜索词的当前前缀匹配。如果匹配,且已经选出的推荐产品少于3个,它将该产品加入临时列表并从堆中弹出。如果不匹配或已达到三个推荐产品的限制,它将停止当前字符的检查。在每个字符的推荐完成后,它将临时列表中的产品重新压入堆中以供下一轮使用。

时间复杂度:

O(k n log n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么选择最小堆来处理产品数组而不是直接对数组进行排序?
使用最小堆而不是直接对数组进行排序的主要原因是,最小堆可以更高效地处理动态数据集合。在这个算法中,需要频繁地插入和删除元素(每次检查一个字符后调整堆),最小堆可以在对数时间内完成这些操作,而对于排序数组,插入和删除操作可能需要线性时间。此外,使用最小堆可以直接访问当前最小的元素,这在实际操作中可以更快地找到匹配的前缀。
🦆
在算法中,如果堆顶的产品不符合搜索条件时直接弹出,这是否意味着这些产品在后续的检索中将不再被考虑?这样做是否可能漏掉某些符合条件的产品?
是的,如果堆顶的产品一旦被判断为不符合当前搜索条件并被弹出,它将不会在此次搜索中被重新考虑。这样做确实存在漏掉符合条件的产品的风险,特别是在搜索词的后续字符可能重新使这些产品变为符合条件的情况下。因此,这种方法可能需要更多的逻辑来确保不会漏掉符合条件的产品,或者在实现时采取不同的策略来确保所有可能的产品都被适当地考虑。
🦆
题解中提到,每次循环结束后会将临时列表中的产品重新压入堆中,这样做是否会导致重复的检查并影响效率?
是的,将临时列表中的产品重新压回堆中确实可能导致在随后的搜索中重复检查这些产品,这可能会影响算法的效率。每次字符的推荐完成后,重新压入的产品将再次参与堆操作和匹配,可能增加了额外的计算负担。这种重复检查可以通过使用更加高效的数据结构或优化算法逻辑来减少。
🦆
当searchWord的长度大于products中某个产品的长度时,算法如何处理这种情况?
在题解中,当searchWord的长度大于某个产品的长度时,该产品会在匹配过程中被弹出堆且不再被重新考虑,因为它不可能符合当前的搜索条件。这是因为如果产品长度已小于当前搜索词的长度,那么它无法匹配更长的搜索词前缀。这样的处理确保了只有那些长度足够并可能符合搜索要求的产品才会被考虑。

相关问题