LeetCode 65. Valid Number(合法数字→最差的题!)

题目描述:

    Validate if a given string is numeric.

例子:
"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false
"2e10" => true

注意:It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.

分析:
    题意:给定一个字符串,判断它是否为数字。

    思路:据说这道题是LeetCode史上最差的题,因为验证规则没有讲清楚,所以好多bad cases很难想到。

LeetCode 65

    如图所示,先给出了数字的整体模式:整体符号(+, 1) | 整型数字(0→9) | 小数点(.) | 小数部分(0→9) | 科学记数符号(e, E) | 科学记数符号(+, 1) | 科学记数数字(0→9),然后给出了一些特殊的例子和判定结果。我总结了以下规则:
    ① 一定要有数字出现,如果出现科学记数符号e/E,前后都必须有数字。
    ② 如果出现科学记数符号e/E,前面的数字可以是整型、小数型,后面的数字必须是整型;前后都可以出现数字正负号。
    ③ 数字正负号的位置必须在第一个位置或者科学记数符号e/E后一个位置科学记数符号e/E前后,各自最多只能出现一次。
    ④ 如果出现小数点,且整数部分或者是小数部分是零,可以局部省略(1.0→1.,0.1→.1,但是根据规则①,0.0不能同时省略数字)。
    ⑤ 小数点和科学记数符号e/E不能重复出现。

    这里分别给出了:Ⅰ. 我自己第一遍的AC代码;Ⅱ. 我参考别人思路实现的比较优雅的代码。
    假设字符串长度为n,时间复杂度为O(n)。

代码():

#include <bits/stdc++.h>

using namespace std;

// string
// Accepted
class Solution {
public:
    bool isNumber(string s) {
        int n = s.length();
		// Exceptional Case: 
		if(n == 0){
			return true;
		}
		// remove the blanks from the left and the right
		int start = 0, end = n - 1;
		while(start <= n - 1 && s[start] == ' '){
			start++;
		}
		if(start == n){
			return false;
		}
		while(end >= 0 && s[end] == ' '){
			end--;
		}
		// start -> end
		int cnt_sign = 0, pos_sign_1 = -1, pos_sign_2 = -1;
		int cnt_points = 0, pos_point = -1;
		int cnt_es = 0, pos_e = -1;
		int cnt_digits = 0, pos_digit = -1;
		for(int i = start; i <= end; i++){
			if(s[i] == '+' || s[i] == '-'){
				cnt_sign++;
				if(cnt_sign == 1){
					pos_sign_1 = i;
				}
				else if(cnt_sign == 2){
					pos_sign_2 = i;
				}
			}
			else if(s[i] == '.'){
				cnt_points++;
				pos_point = i;
			}
			else if(s[i] == 'e'){
				cnt_es++;
				pos_e = i;
			}
			else if(s[i] >= '0' && s[i] <= '9'){
				cnt_digits++;
				if(pos_digit == -1){
					pos_digit = i;
				}
			}
			// ' ', 'a', 'b', 'c', 'E'...
			else{
				return false;
			}
		}
		if(cnt_sign >= 3 || cnt_points >= 2 || cnt_es >= 2){
			return false;
		}
		if(cnt_sign >= 2 && cnt_es == 0){
			return false;
		}
		if(cnt_es == 0){
			if(cnt_digits == 0){
				return false;
			}
			if(cnt_sign == 1 && pos_sign_1 != start){
				return false;
			}
			if(cnt_points == 1 && !((pos_point - 1 >= start && s[pos_point - 1] >= '0' && s[pos_point - 1] <= '9') || (pos_point + 1 <= end && s[pos_point + 1] >= '0' && s[pos_point + 1] <= '9'))){
				return false;
			}
		}
		else if(cnt_es == 1){
			if(cnt_digits == 0 || (cnt_digits >= 1 && pos_digit >= pos_e)){
				return false;
			}
			if(!(s[end] >= '0' && s[end] <= '9')){
				return false;
			}
			if(pos_e == start || pos_e == end){
				return false;
			}
			if(cnt_points == 1 && pos_point >= pos_e){
				return false;
			}
			if(cnt_points == 1 && !((pos_point - 1 >= start && s[pos_point - 1] >= '0' && s[pos_point - 1] <= '9') || (pos_point + 1 <= end && s[pos_point + 1] >= '0' && s[pos_point + 1] <= '9'))){
				return false;
			}
			if(cnt_sign == 1 && !((pos_sign_1 == start) || (pos_sign_1 == pos_e + 1))){
				return false;
			}
			if(cnt_sign == 2 && !((pos_sign_1 == start) && (pos_sign_2 == pos_e + 1))){
				return false;
			}
		}
		return true;
    }
};

代码():

#include <bits/stdc++.h>

using namespace std;

class Solution {
public:
    bool isNumber(string s) {
		// trim
		s.erase(0, s.find_first_not_of(" "));
		s.erase(s.find_last_not_of(" ") + 1);
		// a couple of flags
		bool pointSeen = false;
		bool eSeen = false;
		bool numberSeen = false;
		// bool numberAfterE = true; also correct!
		bool numberAfterE = false;
		// one pass
		int n = s.length();
		for(int i = 0; i <= n - 1; i++){
			if(s[i] >= '0' && s[i] <= '9'){
				numberSeen = true;
				numberAfterE = true;
			}else if(s[i] == '.'){
				if(eSeen || pointSeen){
					return false;
				}
				pointSeen  = true;
			}else if(s[i] == 'e'){
				if(eSeen || !numberSeen){
					return false;
				}
				numberAfterE = false;
				eSeen = true;
			}else if(s[i] == '+' || s[i] == '-'){
				if(i != 0 && s[i - 1] != 'e'){
					return false;
				}
			}else{
				return false;
			}
		}
		// get answer
		return numberSeen && numberAfterE;
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值