LeetCode 第 65 題(Valid Number)

liyuanbhu發表於2016-05-01

LeetCode 第 65 題(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.

這道題是 LeetCode 的提交成功率最低的一道題,Acceptance 只有 12.1%。

其實倒不是這道題有多難,只是要考慮的情況比較多。都考慮清楚了,這道題也就做出來了。

首先呢,輸入的字串的前後可能會有多餘的空格。因此第一步預處理就要把多餘的空格去掉。下面的程式碼可以 完成這個功能。

string trim(string s)
{
    string::const_iterator p1 = s.cbegin();
    string::const_iterator p2 = s.cend();

    while(p1 != s.cend())
    {
        if(*p1 != ' ')
        {
            break;
        }
        ++ p1;
    }
    if(p1 == s.cend()) return string();

    while(--p2 != p1)
    {
        if( *p2 != ' ')
        {
            break;
        }
    }

    string ret(p1, ++p2);
    return ret;
}

一個合理的數字要滿足些什麼條件?我簡單的歸納了一下。應該有下面幾點。
1.可能出現的字元包括”+-1234567890.eE”,出現其餘的字元都說明不是合理的數字表示。
2.“+-”號只能出現在兩個地方,字串的最前面和 “eE” 之後緊貼著“eE”。
3.“.” 只能出現一次,而且“.”的前後必須有一邊緊挨著數字。
4.“eE” 也只能出現一次,並且後面要跟著數字,“eE” 的前面只能是數字或“.”。
5.必須要出現數字,也就是 “12345678980” 至少要出來一個。
6.“+-”號後面要跟著數字或“.”。

下面是違反了這 6 條的一些例子:

  • “ABC123” -> 不滿足第 1 條。
  • “12-2” -> 不滿足第 2 條。
  • “.” -> 不滿足第 3 條。
  • “..” -> 不滿足第 3 條。
  • “3.e” -> 不滿足第 4 條。
  • “3.e.” -> 不滿足第 3 條 和 4 條。
  • “” -> 不滿足第 5 條。
  • “-5e-” -> 不滿足第 6 條。
  • “.1e” -> 不滿足第 4 條。

只要滿足這 6 條,構成的字串就是合理的數字表示。下面的程式碼就能完成對這六條規則的檢測。程式碼不復雜,基本的原理是維護了一個狀態機,當遍歷完字串後,如果狀態機處在正確的狀態上則說明這個字串是合法的。

bool isNumber(string s)
{
    s = trim(s); // 刪除前後多餘的空格
    if(s.length() == 0) return false;
    int state = 0; // 0 表示狀態不確定  'e' 表示出現了 e , 2 表示是合法的數字
    int dot = 0; // 暫時還沒有出現小數點
    int eE = 0; // 暫時還沒有出現 e 或 E,所以 eE 的值為 0
    string::const_iterator p = s.cbegin();
    if(*p == '-' || *p == '+') ++p; // +- 號只能出現在兩個位置,這是其中之一
    if(*p == '.')
    {
        dot = 1;
        state = '.';// 特殊狀態,後面必須有數字
        ++p;
    }
    while(p != s.cend())
    {
        char c = tolower(*p);
        if(state == 'e')
        {
            if(*p == '-' || *p == '+') // 這時 "+-" 號可以出現的另一合法位置
            {
                ++p;
                continue;
            }
        }
        if(isdigit(c))
        {
            state = 2;
            ++ p;
            continue;
        }
        if(c == 'e')
        {
            if(state != 2) return false;// 必須出現在數字或 . 之後
            state = 'e';
            eE ++;
            if(eE > 1) return false;
            ++ p;
            continue;
        }
        if( c == '.')
        {
            if(eE) return false;// . 不能出現在 e 的後面
            state = 2;
            dot ++;
            if(dot > 1) return false;
            ++ p;
            continue;
        }
        else
        {
            return false;
        }
    }
    if(state == 2)
        return true;
    else
        return false;
}

相關文章