【LeetCode(Java) - 642】设计搜索自动补全系统

1、题目描述

在这里插入图片描述

2、解题思路

  本题其实考的是对数据结构的掌握。

  先把输入的句子 sentences 按首字母分类存放。

  a - z 总共有 26 个字母,因此创建一个数组,容量为 26,数组的元素为 HashMap,键为句子,值为输入的次数。

  arr[0] 保存 ‘a’ 开头,arr[1] 保存 ‘b’ 开头,。。。,arr[25] 保存 ‘z’ 开头。

  比如:“ababc” 出现了 5 次,则 arr[0] = {“ababc”, 5} (中括号表示 HashMap)

  这样,当调用 input 方法时,如果不是结束字符,则直接根据已输入字符构成的句子 curSent 的首字符从 arr 数组中找。

  比如,curSent = “zoon” ,那么我们直接从 arr[25] 中找匹配的句子,拿 curSent 遍历去找 arr[25] 中的所有句子,找出以 “zoon” 开头的句子存入 list 中。

  接着对 list 进行排序,排序的依据是句子的 times,大在前,小在后。如果一样,则按照字典序。

  最终返回的结果句子取 list 的前 3 个,不足 3 个则全部返回。

3、解题代码

class AutocompleteSystem {
    
    

    // 数组的每一个元素都是一个 HashMap,key 为句子,value 为出现次数
    // arr[0] 表示以字符 'a' 开头的句子
    // arr[1] 表示以字符 'b' 开头的句子
    // ...
    // 以此类推,arr[25] 表示以字符 'z' 开头的句子
    HashMap<String, Integer>[] arr;

    String curSent = "";   // 用于存放句子

    class Node {
    
    
        Node(String st, int t) {
    
    
            sentence = st;
            times = t;
        }

        String sentence;
        int times;
    }

    public AutocompleteSystem(String[] sentences, int[] times) {
    
    
        arr = new HashMap[26];
        // 初始化数组每一个元素的 HashMap
        for (int i = 0; i < 26; i++) {
    
    
            arr[i] = new HashMap<String, Integer>();
        }
        // 把句子分门别类放入 arr 中
        for (int i = 0; i < sentences.length; i++) {
    
    
            // 减去 'a' 表示减去 a 的 ascii 码,得到的就是数组的索引
            arr[sentences[i].charAt(0) - 'a'].put(sentences[i], times[i]);
        }
    }

    public List<String> input(char c) {
    
    
        List<String> res = new ArrayList<>();   // 存放即将返回的补全的句子
        if (c == '#') {
    
     // 如果已经结束输入
            // cur_sent 新存入历史记录中
            // map.getOrDefault(cur_sent, 0) 表示如果 map 中没有 key 为 cur_sent 的元素,则新建一个 key 为 cur_sent 的元素,值为 0
            arr[cur_sent.charAt(0) - 'a'].put(
                    cur_sent,
                    arr[cur_sent.charAt(0) - 'a'].getOrDefault(cur_sent, 0) + 1
            );
            cur_sent = "";
        } else {
    
        // 尚未结束输入
            List<Node> list = new ArrayList<>();    // 存放所有可能的补全句子
            cur_sent += c;  // 待搜索的句子
            for (String key : arr[cur_sent.charAt(0) - 'a'].keySet()) {
    
    
                if (key.indexOf(cur_sent) == 0) {
    
    
                    // 如果 cur_sent 是 key 的前缀,则符合要求,添加到 list 中
                    list.add(new Node(key, arr[cur_sent.charAt(0) - 'a'].get(key)));
                }
            }
            // 对 list 进行排序,如果 times 不相等,则 times 大的在前面
            // 如果 times 相等,则按照字典序
            list.sort((a, b) -> a.times == b.times ? a.sentence.compareTo(b.sentence) : b.times - a.times);
            // 最多只需要三条句子,不够三条就有多少返回多少
            for (int i = 0; i < Math.min(3, list.size()); i++) {
    
    
                res.add(list.get(i).sentence);
            }
        }
        return res;
    }
}

/**
 * Your AutocompleteSystem object will be instantiated and called as such:
 * AutocompleteSystem obj = new AutocompleteSystem(sentences, times);
 * List<String> param_1 = obj.input(c);
 */

猜你喜欢

转载自blog.csdn.net/qq_29051413/article/details/108550456