问题描述
在开发SQL编辑器时,实现自动补全功能是提高用户体验的重要一环。小C需要实现一个功能,根据用户输入的字符片段,快速从已知的SQL关键字和数据库相关名称中找到所有以该片段开头的候选词,并按字典序输出。
例如,当用户输入 s 时,编辑器需要自动提示以 s 开头的所有可能选项,如 select。如果用户输入 fr,则需要提示 from 和 from_mobile。如果在提示中只有一个选项符合,如输入 from_ 时只提示 from_mobile。
测试样例
样例1:
输入:
num = 8,data = ["select", "from", "where", "limit", "origin_log_db", "event_log_table", "user_id", "from_mobile"], input = "f"
输出:'from,from_mobile'
样例2:
输入:
num = 8,data = ["select", "from", "where", "limit", "origin_log_db", "event_log_table", "user_id", "from_mobile"], input = "wh"
输出:'where'
样例3:
输入:
num = 8,data = ["select", "from", "where", "limit", "origin_log_db", "event_log_table", "user_id", "from_mobile"], input = "z"
输出:'-1'
样例4:
输入:
num = 8,data = ["select", "from", "where", "limit", "origin_log_db", "event_log_table", "user_id", "from_mobile"], input = "origin"
输出:'origin_log_db'
思路解析
1. 遍历查找
遍历 data 数组,检查每个字符串是否以 input 开头。如果是,则将其添加到结果列表中。
2. 去重
使用一个 map 来记录已经添加到结果列表中的字符串,避免重复添加。
3. 排序
如果结果列表中有多个候选词,按字典序排序。
4. 返回结果
- 如果结果列表为空,返回
"-1"。 - 如果结果列表只有一个元素,直接返回该元素。
- 如果结果列表有多个元素,按字典序排序后,使用逗号连接并返回。
代码实现
package main
import (
"fmt"
"sort"
"strings"
)
func solution(num int, data []string, input string) string {
res := make([]string, 0)
repeat := make(map[string]int)
// 遍历 data 数组,查找以 input 开头的字符串
for i := 0; i < num; i++ {
if strings.HasPrefix(data[i], input) {
if _, ok := repeat[data[i]]; !ok {
res = append(res, data[i])
repeat[data[i]] = 1
}
}
}
// 如果没有符合条件的候选词,返回 "-1"
if len(res) == 0 {
return "-1"
} else if len(res) == 1 {
// 如果只有一个候选词,直接返回该候选词
return res[0]
} else {
// 如果有多个候选词,按字典序排序后,使用逗号连接并返回
sort.Strings(res)
return strings.Join(res, ",")
}
}
代码解析
-
初始化:
res:用于存储符合条件的候选词。repeat:用于记录已经添加到res中的字符串,避免重复添加。
-
遍历查找:
- 使用
for循环遍历data数组。 - 使用
strings.HasPrefix检查每个字符串是否以input开头。 - 如果符合条件且未在
repeat中记录过,将其添加到res中,并在repeat中记录。
- 使用
-
返回结果:
- 如果
res为空,返回"-1"。 - 如果
res只有一个元素,直接返回该元素。 - 如果
res有多个元素,使用sort.Strings按字典序排序,然后使用strings.Join将结果列表连接成一个字符串,使用逗号分隔。
- 如果
-
strings函数介绍:
- 字符串是否有某个前缀或后缀
// s 中是否以 prefix 开始
func HasPrefix(s, prefix string) bool {
return len(s) >= len(prefix) && <strong><span style="color:#ff0000;">s[0:len(prefix)]</span></strong> == prefix
}
// s 中是否以 suffix 结尾
func HasSuffix(s, suffix string) bool {
return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
}
- Join
func Join(a []string, sep string) string
将字符串数组(或slice)连接起来可以通过 Join 实现。
标准库的实现:
func Join(a []string, sep string) string {
if len(a) == 0 {
return ""
}
if len(a) == 1 {
return a[0]
}
n := len(sep) * (len(a) - 1)
for i := 0; i < len(a); i++ {
n += len(a[i])
}
b := make([]byte, n) //借助 字节切片实现
bp := <strong><span style="color:#ff0000;">copy</span></strong>(b, a[0])
for _, s := range a[1:] {
bp += copy(b[bp:], sep)
bp += copy(b[bp:], s)
}
return str
总结
通过上述方法,我们可以高效地实现SQL编辑器的自动补全功能。该方法的时间复杂度为 O(n log n),其中 n 是 data 数组的长度。这种方法在处理大规模数据时也能保持较高的效率。