'最长公共前缀'

This commit is contained in:
zhuyijun 2021-04-05 14:26:54 +08:00
parent 95aa943b60
commit 433f70e95d
5 changed files with 221 additions and 0 deletions

View File

@ -0,0 +1,55 @@
package main
import (
"bytes"
"fmt"
)
/**
编写一个函数来查找字符串数组中的最长公共前缀
如果不存在公共前缀返回空字符串""
示例 1
输入strs = ["flower","flow","flight"]
输出"fl"
示例 2
输入strs = ["dog","racecar","car"]
输出""
解释输入不存在公共前缀
提示
0 <= strs.length <= 200
0 <= strs[i].length <= 200
strs[i] 仅由小写英文字母组成
*/
func longestCommonPrefix(strs []string) string {
if len(strs) == 0 {
return ""
}
minlen := len(strs[0])
//获取数组中最短的长度
for _, str := range strs {
if len(str) < minlen {
minlen = len(str)
}
}
var result bytes.Buffer
for i := 0; i < minlen; i++ {
temp := strs[0][i]
for _, str := range strs {
if str[i] != temp {
return result.String()
}
}
result.WriteByte(strs[0][i])
}
return result.String()
}
func main() {
var a =[]string{"abcadc","abcad"}
fmt.Printf(longestCommonPrefix(a))
}

View File

@ -0,0 +1,48 @@
package main
import "fmt"
/**
最长公共前缀的长度不会超过字符串数组中的最短字符串的长度
minLength 表示字符串数组中的最短字符串的长度则可以在
[0,minLength] 的范围内通过二分查找得到最长公共前缀的长度
每次取查找范围的中间值 mid判断每个字符串的长度为mid 的前缀是否相同
如果相同则最长公共前缀的长度一定大于或等于 mid如果不相同则
最长公共前缀的长度一定小于mid通过上述方式将查找范围缩小一半
直到得到最长公共前缀的长度
*/
func longestCommonPrefix(strs []string) string {
if len(strs) == 0 {
return ""
}
isCommonPrefix := func(length int) bool {
str0, count := strs[0][:length], len(strs)
for i := 1; i < count; i++ {
if strs[i][:length] != str0 {
return false
}
}
return true
}
minLength := len(strs[0])
for _, s := range strs {
if len(s) < minLength {
minLength = len(s)
}
}
low, high := 0, minLength
for low < high {
mid := (high - low + 1) / 2 + low
if isCommonPrefix(mid) {
low = mid
} else {
high = mid - 1
}
}
return strs[0][:low]
}
func main() {
var a =[]string{"abcadc","abcad"}
fmt.Printf(longestCommonPrefix(a))
}

View File

@ -0,0 +1,44 @@
package main
import "fmt"
/**
分治
以使用分治法得到字符串数组中的最长公共前缀对于问题 LCP(Si...Sj)
可以分解成两个子问题LCP(Si...Smind)与LCP(Smd+1...Sj),其中mid =(i+j)/2
对两个子问题分别求解然后对两个子问题的解计算最长公共前缀即为原问题的解
*/
func longestCommonPrefix(strs []string) string {
if len(strs) == 0 {
return ""
}
var lcp func(int, int) string
lcp = func(start, end int) string {
if start == end {
return strs[start]
}
mid := (start + end) / 2
lcpLeft, lcpRight := lcp(start, mid), lcp(mid + 1, end)
minLength := min(len(lcpLeft), len(lcpRight))
for i := 0; i < minLength; i++ {
if lcpLeft[i] != lcpRight[i] {
return lcpLeft[:i]
}
}
return lcpLeft[:minLength]
}
return lcp(0, len(strs)-1)
}
func min(x, y int) int {
if x < y {
return x
}
return y
}
func main() {
var a =[]string{"abcadc","abcad"}
fmt.Printf(longestCommonPrefix(a))
}

View File

@ -0,0 +1,47 @@
package main
import "fmt"
/**
lcp(S1~Sn) = lcp(lcp(lcp(S1,S2),S3),....Sn)
字符串数组两个字符串两个字符串进行求公共最长前缀依次向右移动直至移动到最后返回最长子串
如果在尚未遍历完所有的字符串时最长公共前缀已经是空串则最长公共前缀一定是空串因此不需要继续遍历剩下的字符串直接返回空串即可
*/
func longestCommonPrefix(strs []string) string {
//如果strs数组为空这返回""
if len(strs) == 0 {
return ""
}
prefix := strs[0]
count := len(strs)
for i := 1; i < count; i++ {
prefix = lcp(prefix, strs[i])
if len(prefix) == 0 {
break
}
}
return prefix
}
//两个字符串公共子串
func lcp(str1, str2 string) string {
length := min(len(str1), len(str2))
index := 0
for index < length && str1[index] == str2[index] {
index++
}
return str1[:index]
}
func min(x, y int) int {
if x < y {
return x
}
return y
}
func main() {
var a =[]string{"abcadc","abcad"}
fmt.Printf(longestCommonPrefix(a))
}

View File

@ -0,0 +1,27 @@
package main
import "fmt"
/**
方法一是横向扫描依次遍历每个字符串更新最长公共前缀另一种方法是纵向扫描
纵向扫描时从前往后遍历所有字符串的每一列比较相同列上的字符是否相同
如果相同则继续对下一列进行比较如果不相同则当前列不再属于公共前缀
当前列之前的部分为最长公共前缀
*/
func longestCommonPrefix(strs []string) string {
if len(strs) == 0 {
return ""
}
for i := 0; i < len(strs[0]); i++ {
for j := 1; j < len(strs); j++ {
if i == len(strs[j]) || strs[j][i] != strs[0][i] {
return strs[0][:i]
}
}
}
return strs[0]
}
func main() {
var a =[]string{"abcadc","abcad"}
fmt.Printf(longestCommonPrefix(a))
}