SQL代码补全功能 | 豆包MarsCode AI刷题

154 阅读4分钟

问题拆解

  1. 匹配前缀

    • 对于给定的输入前缀,我们需要遍历数据集,找到所有以该前缀开头的字符串。
    • 这种操作可以通过字符串的 startsWith() 方法来完成,该方法检查一个字符串是否以另一个字符串开头。
  2. 排序

    • 查找出所有匹配的字符串后,题目要求我们将这些字符串按字典顺序进行排序。
    • 在 Java 中,可以通过 Collections.sort() 来对一个字符串列表进行字典排序。
  3. 返回结果

    • 如果有匹配项,将它们按字典顺序连接成一个以逗号分隔的字符串。
    • 如果没有匹配项,则返回 "-1"

数据结构和算法

  1. Set:为了避免重复匹配,我们可以使用 LinkedHashSet 来存储匹配的字符串。LinkedHashSet 可以保证集合中的元素是唯一的,并且保留元素插入的顺序。
  2. List:匹配完成后,我们需要将 Set 中的元素转化为 List,以便进行排序。排序完成后,我们可以将 List 中的元素转化为逗号分隔的字符串。

解决方案步骤

  1. 遍历数据集

    • 对每个单词,使用 startsWith(input) 方法检查该单词是否以输入前缀 input 开头。如果是,就将它加入到 Set 中。
  2. 排序

    • 将 Set 转换为 List,然后用 Collections.sort() 对列表进行字典排序。
  3. 结果处理

    • 如果 Set 为空,说明没有找到匹配的字符串,返回 "-1"
    • 否则,使用 String.join(",", sortedList) 将排序后的字符串列表连接成一个逗号分隔的字符串。

代码实现

import java.util.*;

public class AutoComplete {

    public static String solution(int n, String[] wordList, String input) {
        // 用于存储匹配的候选项
        Set<String> candidates = new LinkedHashSet<>();
        
        // 遍历每个词,检查是否以 input 为前缀
        for (String word : wordList) {
            if (word.startsWith(input)) {
                candidates.add(word); // 如果匹配,加入集合
            }
        }
        
        // 如果没有匹配项,返回 -1
        if (candidates.isEmpty()) {
            return "-1";
        }
        
        // 将候选项转为列表并排序
        List<String> sortedCandidates = new ArrayList<>(candidates);
        Collections.sort(sortedCandidates);
        
        // 将排序后的候选项连接为一个逗号分隔的字符串
        return String.join(",", sortedCandidates);
    }

    public static void main(String[] args) {
        // 测试用例
        String[] testData1 = {"select", "from", "where", "limit", "origin_log_db", "event_log_table", "user_id", "from_mobile"};
        String[] testData2 = {"select", "from", "where", "limit", "group", "having", "in", "index", "inner", "insert", "like", "log_db", "log_table", "user_id", "group_name", "group_id"};
        
        System.out.println(solution(8, testData1, "f"));  // Expected: "from,from_mobile"
        System.out.println(solution(16, testData2, "g")); // Expected: "group,group_name,group_id"
        System.out.println(solution(16, testData2, "m")); // Expected: "-1"
    }
}

代码解析

  1. Set<String> candidates = new LinkedHashSet<>();

    • 使用 LinkedHashSet 来存储匹配的字符串。这样做既能避免重复字符串,又能保持插入顺序。
  2. if (word.startsWith(input)) { candidates.add(word); }

    • 遍历 wordList 数组,对每个字符串检查是否以 input 为前缀。如果是,就将该字符串加入 candidates 集合。
  3. if (candidates.isEmpty()) { return "-1"; }

    • 如果没有找到任何匹配项,直接返回 "-1"
  4. List<String> sortedCandidates = new ArrayList<>(candidates);

    • 将 Set 转换为 List,方便后续排序操作。
  5. Collections.sort(sortedCandidates);

    • 对匹配的候选项进行字典排序。
  6. return String.join(",", sortedCandidates);

    • 使用 String.join(",", sortedCandidates) 将排序后的列表元素连接成一个以逗号分隔的字符串。

边界情况考虑

  1. 无匹配项

    • 如果没有任何字符串匹配输入的前缀,直接返回 "-1"
  2. 所有字符串匹配

    • 如果所有字符串都匹配,返回字典顺序排序后的所有字符串。
  3. 大小写敏感

    • startsWith() 是大小写敏感的,意味着 "hello" 和 "Hello" 会被认为是不同的字符串。

时间复杂度分析

  1. 遍历数据集:对于每个字符串,调用 startsWith() 方法的时间复杂度是 O(k),其中 k 是前缀的长度。总的时间复杂度是 O(n * k),其中 n 是数据集的大小。
  2. 排序:在最坏的情况下,所有的字符串都会匹配,所以排序的时间复杂度是 O(m log m),其中 m 是匹配的字符串个数。
  3. 总体时间复杂度:最坏情况下的时间复杂度是 O(n * k + m log m)。

总结

这个解决方案通过使用 Set 来去重和保序,利用 startsWith() 方法进行前缀匹配,最终通过 Collections.sort() 来排序匹配项,符合题目要求。