Skip to content

Commit 4a1b87b

Browse files
author
Obsession-kai
committed
update day26/31
1 parent 40c8ac2 commit 4a1b87b

File tree

2 files changed

+156
-0
lines changed

2 files changed

+156
-0
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//题目链接:https://leetcode.cn/problems/ba-zi-fu-chuan-zhuan-huan-cheng-zheng-shu-lcof/?envType=study-plan&id=lcof
2+
// day26/31
3+
// 第 26 天主题为:字符串(中等)
4+
// 包含两道题目:
5+
// 剑指offer20.表示数值的字符串
6+
// 剑指offer67.把字符串转换成整数
7+
8+
package main
9+
10+
// 模拟即可
11+
// 官方题解的解法是:确定有限状态自动机,这块我不太懂,有兴趣的同学自行了解哈
12+
func isNumber(s string) bool {
13+
n := len(s)
14+
// 若字符串长度为0,无法表示数值
15+
if n == 0{
16+
return false
17+
}
18+
// 从下标0开始遍历
19+
index := 0
20+
// 读取字符开头处的若干空格
21+
for index < n && s[index] == ' '{
22+
index ++
23+
}
24+
// 读取整数部分,,numeric代表读取到index是否为数值
25+
// index 持续向前推进
26+
numeric := ScanInteger(s,&index)
27+
// 若下一个字符为'.',说明为小数,读取小数部分
28+
if index < n && s[index] == '.'{
29+
index ++
30+
// 这里用逻辑或的原因:
31+
// 1. '.'前若无数字,则'.'后至少需要一位数字
32+
// 对应左表达式为 true,右表达式为 false
33+
// 2.'.'前有数字,则后方可以有也可以没有数字
34+
// 对应左true右true 和 左false右true
35+
numeric = ScanUnsignedInteger(s,&index) || numeric
36+
}
37+
// 若出现e,后面需要跟一个整数,原理同上
38+
if index < n && (s[index] == 'e' || s[index] == 'E'){
39+
index ++
40+
numeric = numeric && ScanInteger(s,&index)
41+
}
42+
// 读取字符串结尾处的若干空格
43+
for index < n && s[index] == ' '{
44+
index ++
45+
}
46+
// 若 numeric 为 true,且读取到字符串末尾,说明为数值
47+
return numeric && index == len(s)
48+
}
49+
50+
// 读取字符串s从下标index开始的有符号整数
51+
func ScanInteger(s string,index *int) bool{
52+
// 先读取正负号,若无符号,默认正数
53+
if *index < len(s) && (s[*index] == '+' || s[*index] == '-'){
54+
*index ++
55+
}
56+
// 读取符号后,读取无符号整数
57+
return ScanUnsignedInteger(s,index)
58+
}
59+
60+
// 读取字符串s从下标index开始的无符号整数
61+
// 若未读取到无符号整数,返回false,否则,返回true
62+
func ScanUnsignedInteger(s string,index *int) bool {
63+
start_of_integer := *index
64+
// 根据ASCII码判断是否为数字字符
65+
// 若读取到非数字字符,直接跳出即可
66+
for *index < len(s) && s[*index] >= '0' && s[*index] <= '9'{
67+
*index ++
68+
}
69+
// 若*index大于读取前的值,说明有整数被读取到
70+
return *index > start_of_integer
71+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//题目链接:https://leetcode.cn/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof/?envType=study-plan&id=lcof
2+
package main
3+
4+
//这里我想先解释一下为什么负数范围比正数范围大 1 .
5+
//因为对有符号数,在计算机中表达时,最高位约定为符号位,符号位为 0 时代表正数,符号位为 1 时代表负数。
6+
//对 int32,真正表达数值的部分就是剩下的 31 位,正数范围很容易理解为 1~2^31-1(2147483647)
7+
//有一个特殊的值,就是 0 值,对符号位 1 和 0 的时候,都是 0,用两个形式表达同一个数无疑是浪费的,
8+
//所以,我们就规定,符号位为 1 时的全 0,表达 -2147483648,这也是负数表示的范围比正数多1的原因。
9+
//综上,对于任意位的,无论是8位,16位,32位甚至64位的整数类型表示范围的计算公式为:
10+
//如总位数为n位,那么有符号数的范围为:-2^(n-1) ~ 2^(n-1)-1,无符号数的表示范围为:0~2^n-1
11+
12+
13+
//此题解参考自链接:https://leetcode.cn/problems/ba-zi-fu-chuan-zhuan-huan-cheng-zheng-shu-lcof/submissions/
14+
15+
//首部空格: 删除之即可;
16+
//符号位: 三种情况,即 ''+'' , ''-'' , ''无符号" ;新建一个变量保存符号位,返回前判断正负即可。
17+
//非数字字符: 遇到首个非数字的字符时,应立即返回。
18+
//数字字符:
19+
//字符转数字: “此数字的 ASCII 码” 与 “ 00 的 ASCII 码” 相减即可;
20+
//数字拼接: 若从左向右遍历数字,设当前位字符为 c ,当前位数字为 x ,数字结果为 res,则数字拼接公式为:res = 10 * res + x
21+
//x = ascii(c) - ascii('0')
22+
//
23+
//接下来是比较关键的数字越界处理:
24+
//题目要求返回的数值范围应在 [-2^{31}, 2^{31} - 1],因此需要考虑数字越界问题。
25+
//而由于题目指出 环境只能存储 32 位大小的有符号整数 ,因此判断数字越界时,要始终保持 res 在 int 类型的取值范围内。
26+
//
27+
//在每轮数字拼接前,判断 res 在此轮拼接后是否超过 2147483647,若超过则加上符号位直接返回。
28+
//设数字拼接边界 boundary = 2147483647 // 10 = 214748364,则以下两种情况越界:
29+
//
30+
//1. res > boundry, 拼接后越界
31+
//2. res = boundry && x > 7,拼接后越界
32+
//
33+
//这种处理方式非常巧妙,> ‘7’ 这个操作看似只考虑到了最大值,其实也考虑了最小值,只要大于,直接返回即可。
34+
const (
35+
MAX_INT = 1 << 31 - 1
36+
MIN_INT = -1 * (1 << 31)
37+
)
38+
39+
func strToInt(str string) int {
40+
// index 为 str 遍历到的位置
41+
index := 0
42+
// 为防止读取空格出现越界panic,需要提前处理str为空字符或全空格的情况
43+
if str == ""{
44+
return 0
45+
}
46+
for i:=0;i<len(str);i++{
47+
if str[i] != ' '{
48+
break
49+
}
50+
if i == len(str) - 1{
51+
return 0
52+
}
53+
}
54+
// 读取前置空格
55+
for str[index] == ' '{
56+
index ++
57+
}
58+
// 符号位初始化为 0
59+
sign := 1
60+
if str[index] == '+'{
61+
index ++
62+
} else if str[index] == '-' {
63+
sign = -1
64+
index ++
65+
}
66+
boundary := MAX_INT/10
67+
res := 0
68+
for _,s := range str[index:]{
69+
// 读取到非数字字符,直接跳出
70+
if s < '0' || s > '9'{
71+
break
72+
}
73+
// 预计出现越界情况,根据符号位返回最大或最小值
74+
if res > boundary || res == boundary && s > '7'{
75+
if sign == 1{
76+
return MAX_INT
77+
} else {
78+
return MIN_INT
79+
}
80+
}
81+
res = res * 10 + int(s - '0')
82+
83+
}
84+
return sign * res
85+
}

0 commit comments

Comments
 (0)