题目描述
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""
。
示例 1:
输入:strs = ["flower","flow","flight"] 输出:"fl"
示例 2:
输入:strs = ["dog","racecar","car"] 输出:"" 解释:输入不存在公共前缀。
提示:
1 <= strs.length <= 200
0 <= strs[i].length <= 200
strs[i]
仅由小写英文字母组成
分析
通过阅读题目,能够发现其需要对应的公共前缀,提及到公共前缀最容易想到的方法就是通过不断提取对应的单词进行和后面的单词比较,如果出现相同的部分那么就截取出来以便于后续继续迭代比较,如果完全不相同或者是截取出的结果长度为0,那么可以直接按照题目的要求返回空字符串即可。按照这种方式,我们可以想到两种方式:
一种就是中规中矩的上面分析的方式,将第一个字符串提取出来之后与后面的字符串不断比较不断确定公共部分后截取,这样子对于一些公共部分较小的公共前缀所需要的不断截取的次数会比较多,对资源的消耗可能也比较大。
时间复杂度:O(n × L)
另外一种方式是通过快速扫描所有字符串后找出最小长度的字符串后不断和其他字符串比较这里的最小长度内的公共前缀即可,这样截取的次数和对比的次数相对比较小。
时间复杂度:O(n × L)
实际效率比较:
-
相同时间复杂度:两种方法的时间复杂度都是
O(n × L)
,因此从大O记号来看,它们的效率理论上相同。 -
实际效率差异:
- 第一种方法:每次比较时更新
prefix
,并且在每个字符串与prefix
进行比较时都重新计算最小长度。这会带来额外的赋值和切片操作。 - 第二种方法:首先找到最短的字符串,然后直接将最短字符串作为前缀进行比较。由于只做一次切片操作,减少了不必要的赋值和切片操作,因此在实际运行时可能会略微高效一些。
- 第一种方法:每次比较时更新
参考代码
方法一:横向扫描
func LongestCommonPrefix(strs []string) string {
// 如果字符串数组为空,返回空字符串作为公共前缀
if len(strs) == 0 {
return ""
}
// 假设第一个字符串为公共前缀
prefix := strs[0]
// 从第二个字符串开始,依次与当前前缀比较,更新前缀
for i := 1; i < len(strs); i++ {
// 如果当前字符串为空,返回空字符串作为公共前缀
if len(strs[i]) == 0 {
return ""
}
// 找到当前字符串和前缀中较短的长度
minLength := len(prefix)
if len(strs[i]) < minLength {
minLength = len(strs[i])
}
// 从头开始比较当前字符串和前缀的每个字符,找到公共前缀的长度
j := 0
for ; j < minLength; j++ {
// 如果字符不相等,停止比较
if prefix[j] != strs[i][j] {
break
}
}
// 更新前缀为匹配的部分
prefix = prefix[:j]
// 如果前缀已经为空,说明没有公共前缀,直接返回空字符串
if prefix == "" {
return ""
}
}
// 返回最终的公共前缀
return prefix
}
方法二:最短长度前缀扫描
func LongestCommonPrefix(strs []string) string {
// 初始化最短字符串的长度为第一个字符串的长度
minlen := len(strs[0])
// 初始化最短字符串的索引为0,即第一个字符串
minIndex := 0
// 遍历字符串数组,找到最短字符串及其索引
for i, v := range strs {
// 如果当前字符串长度小于已知最短长度,则更新最短长度和最短字符串索引
if len(v) < minlen {
minlen = len(v)
minIndex = i
}
}
// 假设最短的字符串为公共前缀
prefix := strs[minIndex]
// 遍历字符串数组,逐个与最短字符串比较
for i := 0; i < len(strs); i++ {
// 逐字符比较当前字符串与最短字符串
for j := 0; j < minlen; j++ {
// 如果当前前缀为空,说明没有公共前缀,直接返回空字符串
if len(prefix) == 0 {
return ""
}
// 如果字符不匹配,更新前缀为匹配的部分,并退出当前字符比较
if strs[i][j] != strs[minIndex][j] {
prefix = prefix[:j]
break
}
}
}
// 返回最终的公共前缀
return prefix
}