Valid Number 验证数字
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.
这道验证数字的题比想象中的要复杂的多,有很多情况需要考虑,而OJ上给这道题的分类居然是Easy,Why? 而10.9% 的全场最低的Accept Rate正说明这道题的难度,网上有很多解法,有利用有限自动机Finite Automata Machine的程序写的简洁优雅 (http://blog.csdn.net/kenden23/article/details/18696083), 还有利用正则表达式,更是写的丧心病狂的简洁 (http://blog.csdn.net/fightforyourdream/article/details/12900751)。而我主要还是用最一般的写法,参考了网上另一篇博文 (http://yucoding.blogspot.com/2013/05/leetcode-question-118-valid-number.html),处理各种情况。
首先,从题目中给的一些例子可以分析出来,我们所需要关注的除了数字以外的特殊字符有空格 ‘ ’, 小数点 '.', 自然数 'e/E', 还要加上正负号 '+/-", 除了这些字符需要考虑意外,出现了任何其他的字符,可以马上判定不是数字。下面我们来一一分析这些出现了也可能是数字的特殊字符:
1. 空格 ‘ ’: 空格分为两种情况需要考虑,一种是出现在开头和末尾的空格,一种是出现在中间的字符。出现在开头和末尾的空格不影响数字,而一旦中间出现了空格,则立马不是数字。解决方法:预处理时去掉字符的首位空格,中间再检测到空格,则判定不是数字。
2. 小数点 '.':小数点需要分的情况较多,首先的是小数点只能出现一次,但是小数点可以出现在任何位置,开头(".3"), 中间("1.e2"), 以及结尾("1." ), 而且需要注意的是,小数点不能出现在自然数 'e/E' 之后,如 "1e.1" false, "1e1.1" false。还有,当小数点位于末尾时,前面必须是数字,如 "1." true," -." false。解决方法:开头中间结尾三个位置分开讨论情况。
3. 自然数 'e/E':自然数的前后必须有数字,即自然数不能出现在开头和结尾,如 "e" false, ".e1" false, "3.e" false, "3.e1" true。而且小数点只能出现在自然数之前,还有就是自然数前面不能是符号,如 "+e1" false, "1+e" false. 解决方法:开头中间结尾三个位置分开讨论情况。
4. 正负号 '+/-",正负号可以再开头出现,可以再自然数e之后出现,但不能是最后一个字符,后面得有数字,如 "+1.e+5" true。解决方法:开头中间结尾三个位置分开讨论情况。
下面我们开始正式分开头中间结尾三个位置来讨论情况:
1. 在讨论三个位置之前做预处理,去掉字符串首尾的空格,可以采用两个指针分别指向开头和结尾,遇到空格则跳过,分别指向开头结尾非空格的字符。
2. 对首字符处理,首字符只能为数字或者正负号 '+/-",我们需要定义三个flag在标示我们是否之前检测到过小数点,自然数和正负号。首字符如为数字或正负号,则标记对应的flag,若不是,直接返回false。
3. 对中间字符的处理,中间字符会出现五种情况,数字,小数点,自然数,正负号和其他字符。
若是数字,标记flag并通过。
若是自然数,则必须是第一次出现自然数,并且前一个字符不能是正负号,而且之前一定要出现过数字,才能标记flag通过。
若是正负号,则之前的字符必须是自然数e,才能标记flag通过。
若是小数点,则必须是第一次出现小数点并且自然数没有出现过,才能标记flag通过。
若是其他,返回false。
4. 对尾字符处理,最后一个字符只能是数字或小数点,其他字符都返回false。
若是数字,返回true。
若是小数点,则必须是第一次出现小数点并且自然数没有出现过,还有前面必须是数字,才能返回true。
class Solution {
public:
    bool isNumber(string s) {
        int len = s.size();
        int left = , right = len - ;
        bool eExisted = false;
        bool dotExisted = false;
        bool digitExisited = false;
        // Delete spaces in the front and end of string
        while (s[left] == ' ') ++left;
        while (s[right] == ' ') --right;
        // If only have one char and not digit, return false
        if (left >= right && (s[left] < '' || s[left] > '')) return false;
        //Process the first char
        if (s[left] == '.') dotExisted = true;
        else if (s[left] >= '' && s[left] <= '') digitExisited = true;
        else if (s[left] != '+' && s[left] != '-') return false;
        // Process the middle chars
        for (int i = left + ; i <= right - ; ++i) {
            if (s[i] >= '' && s[i] <= '') digitExisited = true;
            else if (s[i] == 'e' || s[i] == 'E') { // e/E cannot follow +/-, must follow a digit
                if (!eExisted && s[i - ] != '+' && s[i - ] != '-' && digitExisited) eExisted = true;
                else return false;
            } else if (s[i] == '+' || s[i] == '-') { // +/- can only follow e/E
                if (s[i - ] != 'e' && s[i - ] != 'E') return false;
            } else if (s[i] == '.') { // dot can only occur once and cannot occur after e/E
                if (!dotExisted && !eExisted) dotExisted = true;
                else return false;
            } else return false;
        }
        // Process the last char, it can only be digit or dot, when is dot, there should be no dot and e/E before and must follow a digit
        if (s[right] >= '' && s[right] <= '') return true;
        else if (s[right] == '.' && !dotExisted && !eExisted && digitExisited) return true;
        else return false;
    }
};
上面的写法略为复杂,我们尝试着来优化一下,根据上面的分析,所有的字符可以分为六大类,空格,符号,数字,小数点,自然底数和其他字符,我们需要五个标志变量,num, dot, exp, sign分别表示数字,小数点,自然底数和符号是否出现,numAfterE表示自然底数后面是否有数字,那么我们分别来看各种情况:
- 空格: 我们需要排除的情况是,当前位置是空格而后面一位不为空格,但是之前有数字,小数点,自然底数或者符号出现时返回false。
- 符号:符号前面如果有字符的话必须是空格或者是自然底数,标记sign为true。
- 数字:标记num和numAfterE为true。
- 小数点:如果之前出现过小数点或者自然底数,返回false,否则标记dot为true。
- 自然底数:如果之前出现过自然底数或者之前从未出现过数字,返回false,否则标记exp为true,numAfterE为false。
- 其他字符:返回false。
最后返回num && numAfterE即可。
解法二:
class Solution {
public:
    bool isNumber(string s) {
        bool num = false, numAfterE = true, dot = false, exp = false, sign = false;
        int n = s.size();
        for (int i = ; i < n; ++i) {
            if (s[i] == ' ') {
                if (i < n -  && s[i + ] != ' ' && (num || dot || exp || sign)) return false;
            } else if (s[i] == '+' || s[i] == '-') {
                if (i >  && s[i - ] != 'e' && s[i - ] != ' ') return false;
                sign = true;
            } else if (s[i] >= '' && s[i] <= '') {
                num = true;
                numAfterE = true;
            } else if (s[i] == '.') {
                if (dot || exp) return false;
                dot = true;
            } else if (s[i] == 'e') {
                if (exp || !num) return false;
                exp = true;
                numAfterE = false;
            } else return false;
        }
        return num && numAfterE;
    }
};
这道题给了例子不够用,下面这些例子都是我在调试的过程中出现过的例子,用来参考:
string s1 = ""; // True
string s2 = " 0.1 "; // True
string s3 = "abc"; // False
string s4 = "1 a"; // False
string s5 = "2e10"; // True string s6 = "-e10"; // False
string s7 = " 2e-9 "; // True
string s8 = "+e1"; // False
string s9 = "1+e"; // False
string s10 = " "; // False string s11 = "e9"; // False
string s12 = "4e+"; // False
string s13 = " -."; // False
string s14 = "+.8"; // True
string s15 = " 005047e+6"; // True string s16 = ".e1"; // False
string s17 = "3.e"; // False
string s18 = "3.e1"; // True
string s19 = "+1.e+5"; // True
string s20 = " -54.53061"; // True string s21 = ". 1"; // False
转自:https://www.cnblogs.com/grandyang/p/4084408.html
Valid Number 验证数字的更多相关文章
- [LeetCode] Valid Number 验证数字
		
Validate if a given string is numeric. Some examples:"0" => true" 0.1 " => ...
 - [LintCode] Valid Number 验证数字
		
Validate if a given string is numeric. Have you met this question in a real interview? Yes Example & ...
 - [LeetCode] 65. Valid Number 验证数字
		
Validate if a given string can be interpreted as a decimal number. Some examples:"0" => ...
 - [Swift]LeetCode65. 有效数字 | Valid Number
		
Validate if a given string is numeric. Some examples:"0" => true" 0.1 " => ...
 - [LeetCode] 125. Valid Palindrome 验证回文字符串
		
Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignori ...
 - [LeetCode] Valid Palindrome 验证回文字符串
		
Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignori ...
 - 【leetcode】Valid Number
		
Valid Number Validate if a given string is numeric. Some examples:"0" => true" 0.1 ...
 - 配置域名服务器报错named[822]: dns_rdata_fromtext  /etc/bind/db.asertest.com mail not a valid number
		
问题描述: 为了配置邮件服务器,更改了相关域名,改完后,重启bind9报错 Mar 17 14:39:39 DnsServer2 named[822]: dns_rdata_fromtext: /et ...
 - C# 验证数字
		
/// <summary> /// 验证数字 /// </summary> /// <param name="number">数字内容</ ...
 
随机推荐
- Lua调用C++时打印堆栈信息
			
公司的手游项目,使用的是基于cocos2d-x绑lua的解决方案(参数quick-x的绑定),虽然使用了lua进行开发,更新很爽了,但是崩溃依然较为严重,从后台查看崩溃日志时,基本上只能靠" ...
 - 使用node-webkit实现打包工具的小结
			
之前一直使用的hta在开发工具,最近转到node-webkit上了,对比一下二者的优劣势.hta单个文件,体积较小,但有兼容性的问题(兼容ie6.7.8就行了,也还好),node-webkit使用we ...
 - Orchard 之:Widget,兼看 Layer 在权限控制中的作用
			
一:Widget 可以理解为控件,可以直接被页面所引用.行为类似与分部页面,比如,我们可以创建一个 商品列表 Widget,然后这个 Widget 就可以被很多页面所引用. 理解 Widget 这个概 ...
 - django外键以及主表和子表的相互查询
			
Django的外键使用 from django.db import models # Create your models here. class Category(models.Model): na ...
 - Java常见异常(Runtime Exception )小结(转)
			
原文链接:Java常见异常(Runtime Exception )小结 Java异常体系结构呈树状,其层次结构图如图 1所示: 本文重在Java中异常机制的一些概念.写本文的目的在 ...
 - Backbone.js 中使用 Model
			
前面几篇 Backbone.js 的例子中有使用到 template, 及数据的填充,其实这已经很接近 Model 了.现在来学习怎么创建自己的 Model 类,并简单的使用.Backbone.js ...
 - Linux系统中最好用的截图软件介绍
			
当我的主力操作系统从 Windows 转换到 Ubuntu 的时候,首要考虑的就是屏幕截图工具的可用性.尽管使用默认的键盘快捷键也可以获取屏幕截图,但如果使用屏幕截图工具,可以更方便地对屏幕截图进行编 ...
 - 解决THINKCMF后台文章的相册图集只能上传一个图片的问题
			
遇到的问题: 最近使用了THINKCMF给客户开发了一个企业网站,客户在使用了一段时间后打电话说后台文章编辑页面有问题 经过沟通过知道,在后台文章编辑和添加页面相册图集每次只能上传一张图片 在跟客 ...
 - oauth2-server-php-docs 存储
			
PDO 概观 PDO存储类使用 PHP 的PDO扩展.这允许连接到MySQL,SQLite,PostgreSQL 等等. 安装 PDO是默认安装的php 5.1+,这个库已经是必需的了,所以你会很好的 ...
 - Skyline开发3-没有注册类0x80040154
			
原生64位程序 我们现在使用的操作系统多为64位系统,其中大部分用的还是32位的软件. 64位软件优点是:可以进行更大范围的整数运算:可以支持更大的内存:除做科学运算的时候取得更好的性能外,不能提高其 ...