剑指 Offer 20. 表示数值的字符串(golang版)

  • 题目描述
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100""5e2""-123""3.1416""-1E-16""0123"都表示数值,但"12e""1a3.14""1.2.3""+-5""12e+5.4"都不是。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
  • 思路
    1、这个题很恶心人,“46.e3”、“3.”、"+.8"等都是数字,而且需要考虑首位的空格字符
    2、暴力求解,E后面必为整数(正负整数),偷个懒将该整体使用strconv.Atoi做判断,不满足直接返回false
    3、其余部分,所有合法的字符对都只能出现一次,“+”和“-”,“E”和“e”,“.”,使用map将这三个分别用1,2,3做个标记,出现过则将map[i]标记为true,相应字符若再出现直接返回false
    4、不考虑E后面的部分,正负号只能出现在第一个字符
    5、题目的恶心之处在于“.”可能出现在第一个或最右一个字符处,需要额外判断,但“.”左右字符至少有一个是数字
    6、E前必须是数字或“.”
    7、弄清楚后写个规则遍历就好

  • 代码

func isNumber(s string) bool {

	//去掉首尾空格
	s = strings.Trim(s," ")
	if len(s) == 0 {
		return false
	}
	//长度为1则必为数字
	if len(s) == 1 {
		_,e := strconv.Atoi(s)
		if e != nil {
			return false
		}
	}

	tmp := make(map[int]bool,3)
	for k,i := range s{
		_,e := strconv.Atoi(string(i))
		if string(i)=="+" || string(i)=="-"  {
			// 正负号只能出现在首位
			if k == 0 {
				tmp[1] = true
			}else{
				return false
			}
		}else if string(i)=="." {
			if tmp[2] {
				return false
			}

			//小数点左右必须有一个为数字
			if k==0 {
				_,e := strconv.Atoi(string(s[k+1]))
				if e != nil  {
					return false
				}
			}else if k == len(s)-1{
				_,e := strconv.Atoi(string(s[k-1]))
				if e != nil  {
					return false
				}
			}else {
				_,e2 := strconv.Atoi(string(s[k-1]))
				_,e3 := strconv.Atoi(string(s[k+1]))
				if e2 != nil && e3 != nil {
					return false
				}
			}
			tmp[2] = true
		}else if string(i) == "E" || string(i) == "e" {
			if tmp[3] {
				return false
			}
			if k>=len(s)-1 || k<=0 {
				return  false
			}
			//e前面必须是数字或".",
			_,e = strconv.Atoi(string(s[k-1]))
			if e != nil &&  string(s[k-1]) != "." {
				return false
			}
			//e后面必须为整数,偷个懒用strconv.Atoi直接判断
			_,e = strconv.Atoi(s[k+1:])
			if e != nil {
				return false
			}else{
				break
			}
		}else if e != nil{
			return false
		}
	}
	return true
}

完整版测试代码

package main

import (
	"fmt"
	"strconv"
	"strings"
)

func main() {
	test()
}



func isNumber(s string) bool {

	//去掉首尾空格
	s = strings.Trim(s," ")
	if len(s) == 0 {
		return false
	}
	//长度为1则必为数字
	if len(s) == 1 {
		_,e := strconv.Atoi(s)
		if e != nil {
			return false
		}
	}

	tmp := make(map[int]bool,3)
	for k,i := range s{
		_,e := strconv.Atoi(string(i))
		if string(i)=="+" || string(i)=="-"  {
			// 正负号只能出现在首位
			if k == 0 {
				tmp[1] = true
			}else{
				return false
			}
		}else if string(i)=="." {
			if tmp[2] {
				return false
			}

			//小数点左右必须有一个为数字
			if k==0 {
				_,e := strconv.Atoi(string(s[k+1]))
				if e != nil  {
					return false
				}
			}else if k == len(s)-1{
				_,e := strconv.Atoi(string(s[k-1]))
				if e != nil  {
					return false
				}
			}else {
				_,e2 := strconv.Atoi(string(s[k-1]))
				_,e3 := strconv.Atoi(string(s[k+1]))
				if e2 != nil && e3 != nil {
					return false
				}
			}
			tmp[2] = true
		}else if string(i) == "E" || string(i) == "e" {
			if tmp[3] {
				return false
			}
			if k>=len(s)-1 || k<=0 {
				return  false
			}
			//e前面必须是数字或".",
			_,e = strconv.Atoi(string(s[k-1]))
			if e != nil &&  string(s[k-1]) != "." {
				return false
			}
			//e后面必须为整数,偷个懒用strconv.Atoi直接判断
			_,e = strconv.Atoi(s[k+1:])
			if e != nil {
				return false
			}else{
				break
			}
		}else if e != nil{
			return false
		}
	}
	return true
}

func test(){
	s := "-."
	if isNumber(s) != false {
		fmt.Println(s)
	}

	s = "3.."
	if isNumber(s) != false {
		fmt.Println(s)
	}

	s = "..3"
	if isNumber(s) != false {
		fmt.Println(s)
	}

	s = "."
	if isNumber(s) != false {
		fmt.Println(s)
	}

	s = ".3"
	if isNumber(s) != true {
		fmt.Println(s)
	}

	s = ".3."
	if isNumber(s) != false {
		fmt.Println(s)
	}

	s = "+.8"
	if isNumber(s) != true {
		fmt.Println(s)
	}

	s = "3."
	if isNumber(s) != true {
		fmt.Println(s)
	}

	s = "46.e3"
	if isNumber(s) != true {
		fmt.Println(s)
	}

	s = ".e1"
	if isNumber(s) != false {
		fmt.Println(s)
	}

	s = "e9"
	if isNumber(s) != false {
		fmt.Println(s)
	}

	s = "+E9"
	if isNumber(s) != false {
		fmt.Println(s)
	}
}
  • 注:确定有限状态自动机,思路更清晰
确定有限状态自动机(以下简称「自动机」)是一类计算模型。它包含一系列状态,这些状态中:

有一个特殊的状态,被称作「初始状态」。
还有一系列状态被称为「接受状态」,它们组成了一个特殊的集合。其中,一个状态可能既是「初始状态」,也是「接受状态」。
起初,这个自动机处于「初始状态」。随后,它顺序地读取字符串中的每一个字符,并根据当前状态和读入的字符,按照某个事先约定好的「转移规则」,从当前状态转移到下一个状态;当状态转移完成后,它就读取下一个字符。当字符串全部读取完毕后,如果自动机处于某个「接受状态」,则判定该字符串「被接受」;否则,判定该字符串「被拒绝」。

注意:如果输入的过程中某一步转移失败了,即不存在对应的「转移规则」,此时计算将提前中止。在这种情况下我们也判定该字符串「被拒绝」。

一个自动机,总能够回答某种形式的「对于给定的输入字符串 S,判断其是否满足条件 P」的问题。在本题中,条件 P 即为「构成合法的表示数值的字符串」。

自动机驱动的编程,可以被看做一种暴力枚举方法的延伸:它穷尽了在任何一种情况下,对应任何的输入,需要做的事情。

自动机在计算机科学领域有着广泛的应用。在算法领域,它与大名鼎鼎的字符串查找算法「KMP」算法有着密切的关联;在工程领域,它是实现「正则表达式」的基础。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值