发现掘金的一个小彩蛋:个人主页,鼠标放置在头像上,头像会转动,越转越快,调皮的程序员。
- 字符串转整数
请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。
函数 myAtoi(string s) 的算法如下:
- 读入字符串并丢弃无用的前导空格
- 检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
- 读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
- 将前面步骤读入的这些数字转换为整数(即,”123” -> 123, “0032” -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
- 如果整数数超过 32 位有符号整数范围 [−231, 231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −231 ,大于 231 − 1 的整数应该被固定为 231 − 1 。
- 返回整数作为最终结果。
注意:
本题中的空白字符只包括空格字符 ‘ ‘ 。
除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/string-to-integer-atoi
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
嗯,出个题连算法都给出来,就挺离谱~~另外,既然是解决文档,当然排除使用Go中的Atoi函数,即strconv包。
本题可以学到的Go知识包括:
- Go中如何将字符转换为对应的数字,即’2’如何转换为数字2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package main import ( "bytes" "encoding/binary" "fmt" ) func main() { s := "0123" s_w1 := int(s[0]) fmt.Println(s_w1) s_w2 := int(s[0] - '0') fmt.Println(s_w2) }
|
为什么删除呢,因为我最初错误的理解为一个byte字节通过二进制操作可转换为int类型,并非如此。在我借鉴的程序中,ByteToInt的形参并非是一个byte,而是[]byte
,即多个byte才能够转换为一个int才对,而’2’,ASCII码0011 0010
转换为整数2,从本质上说,确实为’2’与’0’的差值。
代码中涉及到关于大小端模式:大端模式,数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。而小端模式则是数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。初学的我们不要纠结这些细节,暂时只需要记住“通常,golang中采用的是大端模式”
比如对于数据:0x12345678,从高字节到低字节为:12345678,从低字节到高字节为:78563412。
按照大端模式从低位buf[0]到高位buf[3]则应该为: 12, 34, 56, 78。
按照小端模式从低位buf[0]到高位buf[3]则应该为: 78,56,34,12。
go语言中大小端模式的个人理解
- Go中如何表示数字边界:在整数反转中我们详细介绍了Go中的整数类型,以及如何表示32位整数的数字边界。
1 2 3 4 5
| const MAX_UINT32 = ^uint32(0) const MIN_UINT32 = 0
const MAX_INT32 = int(MAX_UINT32 >> 1) const MIN_INT32 = - MAX_INT32 - 1
|
- Go中如何使用正则表达式:关于正则表达式详细可参考Google关于正则表达式的RE2语法文档,以及维基百科正则表达式。Go常用的正则方法可参考掘金文章:Go正则表达式使用,示例代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package main import ( "fmt" "regexp" ) func main() { buf := "weialfidnd8930232jdjfkdjka09232" reg1 := regexp.MustCompile(`\d.\d`) if reg1 == nil { fmt.Println("regexp err") return }
result1 := reg1.FindAllStringSubmatch(buf, -1) fmt.Println("result1 = ", result1) for _, v := range result1 { fmt.Println("find = ", v[0]) }
match, _ := regexp.MatchString("p([a-z]+)ch", "peach") fmt.Println(match) }
|
个人认为,能够熟练使用正则表达式,网络API,处理集合与列表,是“精通一门语言”的前提,Java也应该包括熟练使用stream库。
查看力扣官网给出的有限状态自动机来解决,也容易理解,不多阐述。我们给出Go语言的正则表达式的解法,参考了力扣中的一个python解法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| import ( "regexp" "strings" )
const MAX_UINT32 = ^uint32(0) const MIN_UINT32 = 0 const MAX_INT32 = int(MAX_UINT32 >> 1) const MIN_INT32 = - MAX_INT32 - 1
func stringToInt(s string) int {
i, num := 0, 0 if s[0] == '-' || s[0] == '+' { i = 1 }
for ; i < len(s); i++ { popNum := int(s[i] - '0') if (num > MAX_INT32/10) || (num == MAX_INT32/10 && popNum > 7) || (num < MIN_INT32/10) || (num == MIN_INT32/10 && popNum < -8) { if s[0] == '-' { return MIN_INT32 } else { return MAX_INT32 } } num = num*10 + popNum }
if s[0] == '-' { return -num } else { return num } }
func myAtoi(s string) int {
str := strings.TrimSpace(s) reg1 := regexp.MustCompile(`^[\+\-]?\d+`)
numArray := reg1.FindAllStringSubmatch(str, 1) if len(numArray) == 0 { return 0 } num := stringToInt(numArray[0][0]) return max(min(num,MAX_INT32), MIN_INT32) }
func min(num1, num2 int) int { if num1 < num2 { return num1 } return num2 }
func max(num1, num2 int) int { if num1 < num2 { return num2 } return num1 }
|
代码比想象中复杂o(╥﹏╥)o
Go语言力扣刷题系列文章 |Go主题月
- Go语言力扣刷题-两数之和|Go主题月
- Go语言力扣刷题-两数相加|Go主题月
- Go语言力扣刷题-无重复字符的最长子串|Go主题月
- Go语言力扣刷题-寻找两个正序数组的中位数|Go主题月
- Go语言力扣刷题-最长回文子串|Go主题月
- Go语言力扣刷题-Z字形变换|Go主题月
- Go语言力扣刷题-整数反转|Go主题月