有限状态机,刷题了解到这个概念时,惊叹了我。故此想要记录一下。
原题剑指 Offer 20. 表示数值的字符串
题目描述
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串”+100”、”5e2”、”-123”、”3.1416”、”0123”都表示数值,但”12e”、”1a3.14”、”1.2.3”、”+-5”、”-1E-16”及”12e+5.4”都不是。
看到这样的题目,给人感觉就是好像思路了解了,但会有好多情况要判断啊。
我能尝试写出的代码是这样子的
1 | fun check(s:String){ |
这样代码,写出来是不放心的,总感觉自己会遗漏某个分支情况。而且写出来后,代码肯定很长很繁琐。
而大佬使用有限状态机的代码是这样的。
1 | class Solution: |
这样的代码看得真的舒服,加上配的状态转移图,逻辑也是清晰很多。大佬的题解
个人的蹩脚的理解
在一个系统中,当前的状态称为现态
,外界输入称为动作
, 随着输入后当前状态改变的结果称为次态
,
次态生成之后便成为新的现态,周而复始。 而次态
的生成,不仅依赖输入,也依赖现态
。这样会有这么一个逻辑,
1 | state = f(state, action) |
而这个函数f
是什么呢?我们可以体会到,它像数学中的条件函数,可以枚举出所有的条件,以及可接受的所有action,
结果也就随之确定。
在这道题中,比如当前状态是,前面是空格(初始状态),下一个字符只能是数字,正负号等等,而不能接受e
等输入。
在这道题目中,我们可以体会到状态区分不是很清晰的,当前状态时之前所有输入的叠加。
代码上,我们用states集合定义所有状态,而其中状态能够接受什么action和转移后的次态,分别用Key-Value表示。
联想日常开发中的相似的东西,当前页面的加载数据的状态。
Init –(request fetch data)–> Loading –(load failed)–> Failed –(retry)–> Loading –(load success)–> Success
这么一个流程,初始页面,请求数据,加载中,加载失败,重试,加载成功。
我们似乎可以意识到,想要达到加载成功
状态,那么之前的状态是确定的,不存在从初始状态
直接跳转到加载成功
,期间必须
经历状态加载中
。 在页面的加载中,似乎可以列举出所有的状态,甚至所有的函数f
,状态转移的关系。
页面加载中,状态较少,输入也少,因而不引入有限状态的概念我们也能理清他们的转移关系。不过,感觉这个概念确实是 个好工具,针对多个状态的场景就很有必要了。但愿以后在业务复杂的场景能够引入这个概念来解决问题。