65. 有效数字
65. 有效数字
难度困难
有效数字(按顺序)可以分成以下几个部分:
- 一个 小数 或者 整数
- (可选)一个
'e'或'E',后面跟着一个 整数
小数(按顺序)可以分成以下几个部分:
- (可选)一个符号字符(
'+'或'-') - 下述格式之一:
- 至少一位数字,后面跟着一个点
'.' - 至少一位数字,后面跟着一个点
'.',后面再跟着至少一位数字 - 一个点
'.',后面跟着至少一位数字
- 至少一位数字,后面跟着一个点
整数(按顺序)可以分成以下几个部分:
- (可选)一个符号字符(
'+'或'-') - 至少一位数字
部分有效数字列举如下:
["2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-123.456e789"]
部分无效数字列举如下:
["abc", "1a", "1e", "e3", "99e2.5", "--6", "-+3", "95a54e53"]
给你一个字符串 s ,如果 s 是一个 有效数字 ,请返回 true 。
示例 1:
输入:s = "0"
输出:true示例 2:
输入:s = "e"
输出:false示例 3:
输入:s = "."
输出:false示例 4:
输入:s = ".1"
输出:true提示:
1 <= s.length <= 20s仅含英文字母(大写和小写),数字(0-9),加号'+',减号'-',或者点'.'。
函数签名:
func isNumber(s string) bool分析
分治
这个问题非常繁琐,这里主要探讨怎么明确地拆分处理。
首先可以删除所有空格,并将所有字母小写,这不会影响结果的正确且能简化问题。
其次,根据 ’e’ 这个字母,来分别处理底数和指数,如果 e 存在,则校验其左侧是不是一个有符号的浮点数,右侧是不是一个有符号的整数——这里把指数的问题消解拆分成了两个子问题。
当然如果不存在字母
e的话只需要判断整个字符串是否代表一个有符号浮点数(或整数)。
判断字符串是否代表一个有符号的浮点数,先判断第一位,如果是正负号则忽略,判断剩余的部分是否是浮点数。判断字符串是否代表一个有符号整数,同样可以先消去首位的正负号影响。
现在的问题是判断字符是否代表浮点数和整数,比较容易。
func isNumber(s string) bool {
s = strings.ReplaceAll(s, " ", "")
s = strings.ToLower(s)
i := strings.Index(s, "e")
if i == -1 {
return isSignedFloat(s)
}
return isSignedFloat(s[:i]) && isSignedInt(s[i+1:])
}
func isSignedFloat(s string) bool {
if len(s) == 0 {
return false
}
if s[0] == '+' || s[0] == '-' {
s = s[1:]
}
return isFloat(s)
}
func isSignedInt(s string) bool {
if len(s) == 0 {
return false
}
if s[0] == '+' || s[0] == '-' {
s = s[1:]
}
return isInt(s)
}
func isFloat(s string) bool {
if len(s) == 0 {
return false
}
if strings.Count(s, ".") > 1 {
return false
}
s = strings.ReplaceAll(s, ".", "")
return isInt(s)
}
func isInt(s string) bool {
if len(s) == 0 {
return false
}
for _, v := range s {
if v < '0' || v >'9' {
return false
}
}
return true
}线性时间复杂度,常数空间复杂度。
状态机
这里引入了状态机的内容。考虑各种状态和状态转移还是非常头大,参考参考力扣官方题解《确定有限状态自动机》。