NO IMAGE

題目:

驗證給定的字串是否為數字。

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

說明: 我們有意將問題陳述地比較模糊。在實現程式碼之前,你應當事先思考所有可能的情況。

更新於 2015-02-10:
C 函式的形式已經更新了。如果你仍然看見你的函式接收 const char * 型別的引數,請點選過載按鈕重置你的程式碼。

 

這道題簡直就是Python 和 C 兩個極致不同的體現。。。

用Python,可以通過一句話就滿足所有邏輯,體現了第三方庫的強大功能。。

class Solution:
def isNumber(self, s):
try:
float(s)
return True
except:
return False

是不是有點想掀桌?我當時冥思苦想想不出結果時也是這心情

 

而用C , 就必須得考慮的非常周全了

總的來說,技巧方面,我們使用了多個布林變數來指明當前的狀態。

步驟方面,首先’ ‘肯定是要跳過的,

class Solution {
public:
bool isNumber(string s) {
//num用來標誌是否是數字, numAfterE用來指代的是e後面的數字是不是數字
//dot用來看有沒有點存在,exp用來看有沒有指數,sign用來看有沒有正負號
bool num = false, numAfterE = true, dot = false, exp = false, sign = false;
int n = s.size();
//遍歷字串
for (int i = 0; i < n;   i) {
//如果是空格
if (s[i] == ' ') {
//如果在我們確定它的狀態後出現空格並且它的後一項又不是空格,那就一定錯誤
if (i < n - 1 && s[i   1] != ' ' && (num || dot || exp || sign)) return false;
}
//如果出現加號或減號
else if (s[i] == ' ' || s[i] == '-') {
//如果不是在第一位,並且前面不是e,並且前面不是空的,則說明是錯誤的
if (i > 0 && s[i - 1] != 'e' && s[i - 1] != ' ') return false;
//當前數字是有符號存在的
sign = true;
}
//碰到了數字
else if (s[i] >= '0' && s[i] <= '9') {
//把數字存在設為true
num = true;
numAfterE = true;
}
//遇到'.'
else if (s[i] == '.') {
//已經有點存在或者有e存在,即在這個點之前出現過了,(看來是不允許1e-2.7這種數的)
if (dot || exp) return false;
dot = true;
}
else if (s[i] == 'e') {
if (exp || !num) return false;//如果前面出現過e或者前面沒出現過num。
exp = true;
//看到第一個e,先把numAfterE設為false,然後看能不能找到數字讓numAfterE變為true
numAfterE = false;
} else return false;
}
//必須要e前面的數字和e後面的數字都正確
return num && numAfterE;
}
};

 

具體判斷原則:

首先,從題目中給的一些例子可以分析出來,我們所需要關注的除了數字以外的特殊字元有空格 ‘ ’, 小數點 ‘.’, 自然數 ‘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

 

以下是一些例子,可以通過這些例子瞭解leetcode對有效數字的判斷標準:

string s1 = "0"; // 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

 

總結:對於多情況討論的題目,要敢於去試驗,並且可以通過設定狀態參量(布林型)來解決判斷。