【Valid Number】cpp
题目:
Validate if a given string is numeric.
Some examples:"0"
=> true
" 0.1 "
=> true
"abc"
=> false
"1 a"
=> false
"2e10"
=> true
Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.
代码:
class Solution { public: bool isNumber(string s) { if ( s.size()<1 ) return false; // escape space from begining and end int index_begin = 0; int index_end = s.size()-1; while ( s[index_begin]==' ' && index_begin<s.size() ) ++index_begin; while ( s[index_end]==' ' && index_end>=0 ) --index_end; // digit, dot, sign, exp enum PreChar{ NONPRE, DIGIT, SIGN, EXP, DOT }; enum PreChar preChar = NONPRE; bool hasDigit = false, hasSign = false, hasExp = false, hasDot = false; int index = index_begin; for ( ;index <= index_end; ++index ) { // space if ( s[index]==' ') return false; // digit if ( s[index]>='0' && s[index]<='9' ) { hasDigit = true; preChar = DIGIT; continue; } // sign if ( s[index]=='+' || s[index]=='-' ){ if ( preChar==EXP || preChar==NONPRE ) { preChar = SIGN; hasSign = true; continue; } else { return false; } } // exp if ( s[index]=='e' || s[index]=='E' ){ if ( (preChar==DIGIT || preChar==DOT) && !hasExp && hasDigit ) { preChar = EXP; hasExp = true; continue; } else { return false; } } // dot if ( s[index]=='.' ){ if ( !hasExp && !hasDot && (preChar==DIGIT || preChar==SIGN || preChar==NONPRE ) ) { preChar = DOT; hasDot = true; continue; } else { return false; } } // illegal input char return false; } // end with digit or dot return preChar==DIGIT || (preChar==DOT && hasDigit); } };
tips:
主要基于这篇blog的思路(http://blog.unieagle.net/2012/11/06/leetcode题目:valid-number/)。在其基础上,对逻辑进行了更系统的梳理和简化。
思路如下:
1. 首先排除字符串首尾的space,这样可以简化判断逻辑(只要在后面的字符串中再出现空格,就一定不是合法数字)
2. 判断剩余的字符串中出现dot('.'), sign('+','-'), exp('e','E'), digit(0~9)是否是合法的。判断的核心逻辑有两个:
a. 上一个出现的字符是什么(即代码中的preChar)
b. dot,sign,exp,digit,是否在之前出现过
这种代码逻辑的好处是:只要认准了两个核心判断逻辑,在这两个核心逻辑之内修修补补,就可以不断地刷test case直到AC。
如果以后有类似的问题,状态条件非常多的,但是输入条件相对固定;并且又需要根据序列化输入条件判断的。
可以多设定几类变量逻辑变量,然后通过判断几类逻辑变量的取值来往下进行;即使不能一次bug free,但是总可以把逻辑补完全。
=====================================================
之前一直看网上的有限状态机(FSM)的做法(http://www.cnblogs.com/chasuner/p/validNumber.html),这种思路的代码非常consice。
FSM怎么运转的,解释的很清晰;但是FSM中这0~8的状态是怎么来的,我并没有看懂,所以只好选择比较一般的方法。
================================================
第二次过这道题,直接照着上次写的代码记忆重复了一下。
class Solution { public: bool isNumber(string s) { if ( s.size()<1 ) return false; // remove blanks both begin and end int i_begin = 0; int i_end = s.size()-1; while ( s[i_begin]==' ' && i_begin<i_end ) ++i_begin; while ( s[i_end]==' ' && i_begin<i_end ) --i_end; enum PreType{ NONE, DIGIT, EXP, SIGN, DOT }; enum PreType preType = NONE; bool hasDigit=false, hasExp=false, hasSign=false, hasDot=false; int i = i_begin; for ( ;i<=i_end; ++i ) { // blank if ( s[i]==' ' ) { return false; } // digit else if ( s[i]>='0' && s[i]<='9' ) { hasDigit = true; preType = DIGIT; } // sign else if ( s[i]=='+' || s[i]=='-' ) { if ( preType==EXP || preType==NONE ) { hasSign=true; preType = SIGN; } else { return false; } } // exp else if ( s[i]=='e' || s[i]=='E' ) { if ( (preType==DIGIT || preType==DOT) && !hasExp && hasDigit ) { hasExp=true; preType=EXP; } else { return false; } } // dot else if ( s[i]=='.' ) { if( !hasExp && !hasDot && (preType==DIGIT || preType==SIGN || preType==NONE ) ) { hasDot=true; preType = DOT; } else { return false; } } else { return false; } } return preType==DIGIT || (preType==DOT && hasDigit); } };
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?