博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Golang面试考题记录 ━━ 最长公共前缀,字符串就是切片,复习[]byte、[]rune、[]uint8、[]int32和单引号
阅读量:4115 次
发布时间:2019-05-25

本文共 4129 字,大约阅读时间需要 13 分钟。

===问:

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 “”。

示例 1:

输入: [“flower”,“flow”,“flight”]

输出: “fl”

示例 2:

输入: [“dog”,“racecar”,“car”]

输出: “”
解释: 输入不存在公共前缀。

说明:

所有输入只包含小写字母 a-z 。

===答:

方法一:

执行用时 :0 ms,击败了100.00% 的用户
内存消耗 :2.4 MB, 击败了27.91%的用户

以字符串长度最短的为参考源,依次比对找到不匹配的跳出,比较符合本人一般的思维模式

func longestCommonPrefix1(strs []string) string {
s := "" l := 0 j := 0 n := 0 m := len(strs) switch m {
case 0: return "" case 1: return strs[0] } // 找到字符最少的字符串 for i, v := range strs {
// 如果有一个字符串为空,则跳出 if len(v) == 0 {
return "" } // 选择最小字符数的 if len(v) < l || l == 0 {
l = len(v) j = i } } // 以字符最少的字符串进行循环 for i, v := range strs[j] {
// 遍历所有字符串 for _, y := range strs {
//如果字符相同,则+1 if string(v) == string(y[i]) {
n++ } } // 如果n的数量和strs的长度相同,则表示都存在该字符,继续循环,否则跳出并返回s if n == len(strs) {
s += string(v) n = 0 } else {
return s } } return s}

方法二:

执行用时 :0 ms, 击败了100.00% 的用户
内存消耗 :2.4 MB, 击败了89.71%的用户

任意一个元素都可以作为参考源,而不是方法一中必须使用字符串长度最短的那个作为参考源。

效率差不多,但是内存消耗似乎稍稍降低了一点点。

func longestCommonPrefix2(strs []string) string {
// 先排除掉一些 l := len(strs) switch l {
// strs为空 case 0: return "" // strs仅一个元素 case 1: return strs[0] } // 设定第一个元素作为前缀的参考源 p := strs[0] // 循环时不含参考源(第一个参考源),少一次比较 for _, x := range strs[1:] {
// 本次元素的长度,内层循环多次需要用到 l = len(x) // 参考源(第一个元素)的各个字符 依次匹配 本元素对应位置的字符, // 一发现有不匹配的就跳出,并修改参考源 for i := range p {
//如果该字符串长度比i的值小了,则表示该字符串已经到头,这样p就停止在本位置 if i >= l {
// p截取最新的,并且跳出循环,下一次循环使用最新的p p = p[:l] break } // 如果同位置字符与参考源同位置字符不同,则修改参考源 if x[i] != p[i] {
// p截取最新的,并且跳出循环,下一次循环使用最新的p p = p[:i] // 这里必须跳出终止本次循环,回到外层循环,找到strs的下一个元素再进行比对 break } } } return p}

===解:

本题在算法层面没什么难度,就是按照一般的思路走就行了,方法二比方法一升级一点。

本题反倒让我在语言层面有所学习:

go语言中字符串默认情况下就是个[]uint8(别名:[]byte)的切片,因此可以直接用切片的方式对其进行切割,而输出的时候又是正常的字符串,例题如下。

s := "a测,123试"fmt.Println(s[:1])   //输出:a,表明英文占1位fmt.Println(s[1:4])  //输出:测,表明中文占3位fmt.Println(s[4:7])  //输出:,,表明中文符号占3位fmt.Println(s[7:10]) //输出:123,表明数字占1位/* 输出a测,123*/

如果使用默认方式,那么当遇到中文等字符的时候,就会占用三个位置,这时使用不当就可能出现乱码。那么为了防止出错,我们可以提前将字符串切片改为[]int32(别名[]rune)形式,输出时再利用string()变回字符串,例题如下。

t := []int32("a测,123试")fmt.Println(t[0], string(t[0]))     // 英文占一位fmt.Println(t[1], string(t[1]))     // 中文占1位fmt.Println(t[2], string(t[2]))     // 中文符号占1位fmt.Println(t[3:6], string(t[3:6])) //数字占1位// 97 a// 27979 测// 65292 ,// [49 50 51] 123

[]uint8(别名[]byte)模式下获得的内容可以直接输出,比如fmt.Println(s[7:10])

[]int32(别名[]rune)模式下获得的内容输出后为int32类型的数值
使用for循环遍历字符串的时候,直接取值v的类型为int32(别名rune),通过索引i取值的类型为int32(别名rune)。在有中文情况下,i的值可能会有间隔

r := "a测,123试"for i, v := range r {
fmt.Printf("%v、v类型:%T,v值:%v;r[i]类型:%T,r[i]值:%v\n", i, v, v, r[i], r[i])}// 0、v类型:int32,v值:97;r[i]类型:uint8,r[i]值:97// 1、v类型:int32,v值:27979;r[i]类型:uint8,r[i]值:230// 4、v类型:int32,v值:65292;r[i]类型:uint8,r[i]值:239// 7、v类型:int32,v值:49;r[i]类型:uint8,r[i]值:49// 8、v类型:int32,v值:50;r[i]类型:uint8,r[i]值:50// 9、v类型:int32,v值:51;r[i]类型:uint8,r[i]值:51// 10、v类型:int32,v值:35797;r[i]类型:uint8,r[i]值:232

单引号包含的内容是字符,其值为int32(别名rune

fmt.Printf("类型:%T,值:%v\n", 'a', 'a')fmt.Printf("类型:%T,值:%v\n", '测', '测')fmt.Printf("类型:%T,值:%v\n", ',', ',')fmt.Printf("类型:%T,值:%v\n", '1', '1')// 类型:int32,值:97// 类型:int32,值:27979// 类型:int32,值:65292// 类型:int32,值:49

上面说过切片可以直接输出,但前提是这个字符串已经存在,如果起始值是数值,或数值型切片,那就必须要使用string()来解析成字符串再输出。

// 整数fmt.Println(int32(27979))         //输出:27979fmt.Println(string(27979))        //输出:测fmt.Println(string(int32(27979))) //输出:测// 切片u := "测"fmt.Println(u[0:3])                                        //输出:测fmt.Println([]int32{
27979}) //输出:[27979]fmt.Println(string([]int32{
27979})) //输出:测fmt.Println(string([]int32{
27979, 27979})) //输出:测测fmt.Println(string([]uint8{
230, 181, 139})) //输出:测fmt.Println(string([]uint8{
230, 181, 139, 230, 181, 139})) //输出:测测// 整数fmt.Println(uint8(97)) //输出:97fmt.Println(string(97)) //输出:a// 切片u = "a"fmt.Println(u[0:1]) //输出:afmt.Println(string([]uint8{
97})) //输出:afmt.Println(string([]uint8{
97, 97})) //输出:aa// 27979// 测// 测// 测// [27979]// 测// 测测// 测// 测测// 97// a// a// a// aa

参考文章:

《》
《》

转载地址:http://ttkpi.baihongyu.com/

你可能感兴趣的文章
Java8 HashMap集合解析
查看>>
自定义 select 下拉框 多选插件
查看>>
fastcgi_param 详解
查看>>
poj 1976 A Mini Locomotive (dp 二维01背包)
查看>>
MODULE_DEVICE_TABLE的理解
查看>>
db db2_monitorTool IBM Rational Performace Tester
查看>>
postgresql监控工具pgstatspack的安装及使用
查看>>
【JAVA数据结构】双向链表
查看>>
【JAVA数据结构】先进先出队列
查看>>
乘法逆元
查看>>
Objective-C 基础入门(一)
查看>>
Flutter Boost的router管理
查看>>
iOS开发支付集成之微信支付
查看>>
C++模板
查看>>
【C#】如何实现一个迭代器
查看>>
【C#】利用Conditional属性完成编译忽略
查看>>
DirectX11 光照演示示例Demo
查看>>
VUe+webpack构建单页router应用(一)
查看>>
Node.js-模块和包
查看>>
(python版)《剑指Offer》JZ01:二维数组中的查找
查看>>