https://leetcode.com/problems/longest-common-prefix/
Write a function to find the longest common prefix string amongst an array of strings.
给定一个string数组,寻找公共的最长前缀;
假设给定数组 ab, ac, ad, 那么最长公共前缀为a
基本思路:
1. 切分出每个字符串的所有前缀,比如abc的前缀为, "", a, ab, abc;
2. 将这些前缀连接成一个新的前缀数组;对于给定的例子, 可以得到,["", a, ab, "", a, ac, "", a, ad]的前缀数组;
3. 那么公共的前缀的,其数量必然等于输入字符数组的总和n;比如 "" 肯定是一个公共前缀,那么在前缀数组总, 必然包含n个 "";
接下来的问题是怎么找到最长的公共前缀;
最简单的方法先排序,然后依次扫描前缀, 并计数;直到找到一个计数少于n的前缀,那么前一个就是最长公共前缀;
但如果排过序了, 其实可以用二分查找的方式更快的找到答案;下面是二分查找的代码:
package main
import (
"fmt"
"sort"
)
func main() {
strs := []string{"flower", "flow", "flight"}
fmt.Printf("%s\n", longestCommonPrefix(strs))
}
func longestCommonPrefix(strs []string) string {
if len(strs) == 0 {
return ""
}
prefix := make([]string, 0, len(strs))
for _, str := range strs {
prefix = appendStrPrefix(prefix, str)
}
sort.Strings(prefix)
return findCommonPrefix(prefix, len(strs))
}
func findCommonPrefix(pres []string, n int) string {
i, j := 0, len(pres)-1
for i <= j {
m := (i + j) / 2
c := countOfPreAt(pres, m)
if c == n {
i = m + 1
} else {
j = m - 1
}
}
return pres[i-1]
}
func countOfPreAt(pres []string, p int) int {
s := pres[p]
i := p
for i >= 0 && pres[i] == s {
i--
}
j := p
for j < len(pres) && pres[j] == s {
j++
}
return (j - 1) - (i + 1) + 1
}
func appendStrPrefix(pre []string, str string) []string {
for i := 0; i <= len(str); i++ {
pre = appendMore(pre, str[:i])
}
return pre
}
func appendMore(strs []string, str string) []string {
if len(strs)+1 == cap(strs) {
tmp := make([]string, len(strs), 2*cap(strs))
copy(tmp, strs)
strs = tmp
}
return append(strs, str)
}