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;
	}
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章