问题拆解
-
匹配前缀:
- 对于给定的输入前缀,我们需要遍历数据集,找到所有以该前缀开头的字符串。
- 这种操作可以通过字符串的
startsWith()方法来完成,该方法检查一个字符串是否以另一个字符串开头。
-
排序:
- 查找出所有匹配的字符串后,题目要求我们将这些字符串按字典顺序进行排序。
- 在 Java 中,可以通过
Collections.sort()来对一个字符串列表进行字典排序。
-
返回结果:
- 如果有匹配项,将它们按字典顺序连接成一个以逗号分隔的字符串。
- 如果没有匹配项,则返回
"-1"。
数据结构和算法
- Set:为了避免重复匹配,我们可以使用
LinkedHashSet来存储匹配的字符串。LinkedHashSet可以保证集合中的元素是唯一的,并且保留元素插入的顺序。 - List:匹配完成后,我们需要将
Set中的元素转化为List,以便进行排序。排序完成后,我们可以将List中的元素转化为逗号分隔的字符串。
解决方案步骤
-
遍历数据集:
- 对每个单词,使用
startsWith(input)方法检查该单词是否以输入前缀input开头。如果是,就将它加入到Set中。
- 对每个单词,使用
-
排序:
- 将
Set转换为List,然后用Collections.sort()对列表进行字典排序。
- 将
-
结果处理:
- 如果
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"
}
}
代码解析
-
Set<String> candidates = new LinkedHashSet<>();- 使用
LinkedHashSet来存储匹配的字符串。这样做既能避免重复字符串,又能保持插入顺序。
- 使用
-
if (word.startsWith(input)) { candidates.add(word); }- 遍历
wordList数组,对每个字符串检查是否以input为前缀。如果是,就将该字符串加入candidates集合。
- 遍历
-
if (candidates.isEmpty()) { return "-1"; }- 如果没有找到任何匹配项,直接返回
"-1"。
- 如果没有找到任何匹配项,直接返回
-
List<String> sortedCandidates = new ArrayList<>(candidates);- 将
Set转换为List,方便后续排序操作。
- 将
-
Collections.sort(sortedCandidates);- 对匹配的候选项进行字典排序。
-
return String.join(",", sortedCandidates);- 使用
String.join(",", sortedCandidates)将排序后的列表元素连接成一个以逗号分隔的字符串。
- 使用
边界情况考虑
-
无匹配项:
- 如果没有任何字符串匹配输入的前缀,直接返回
"-1"。
- 如果没有任何字符串匹配输入的前缀,直接返回
-
所有字符串匹配:
- 如果所有字符串都匹配,返回字典顺序排序后的所有字符串。
-
大小写敏感:
startsWith()是大小写敏感的,意味着"hello"和"Hello"会被认为是不同的字符串。
时间复杂度分析
- 遍历数据集:对于每个字符串,调用
startsWith()方法的时间复杂度是 O(k),其中k是前缀的长度。总的时间复杂度是 O(n * k),其中n是数据集的大小。 - 排序:在最坏的情况下,所有的字符串都会匹配,所以排序的时间复杂度是 O(m log m),其中
m是匹配的字符串个数。 - 总体时间复杂度:最坏情况下的时间复杂度是 O(n * k + m log m)。
总结
这个解决方案通过使用 Set 来去重和保序,利用 startsWith() 方法进行前缀匹配,最终通过 Collections.sort() 来排序匹配项,符合题目要求。