思路
用的是y总代码,说实话要让我自己想是想不出来这个思路的。
y总的那个题解关于字符串非合法数值的判断有几处并不是很好理解,我在此用更通俗的方式来阐述一下:
1. 首先将目标字符串的手段首部和尾部的空格删除(c++利用substr裁剪);
2. 第一次判断:如果裁剪后的字符串为空则返回false;
3. 如果首部有 + 号或者 - 号,去除;
4. 第二次判断,经过步骤3后,若字符串为空或者字符串只有一个小数点则返回false;
5. 定义变量dot记录字符串中小数点数量,定义变量e记录字符串中e的数量,接下来开始循环判断:
- s[i]是数字字符时continue;
- s[i]是小数点时,首先判断在小数点前有无e出现,若出现则返回false;然后判断小数点出现次数是否大于1此,如果大于一次则返回false;
- s[i]是e或E时,首先判断e是否出现在当前字符串的最后一位,若是则返回false;
再判断e是否出现在当前字符串的第一位,若是则返回false;
再判断最特殊的一种情况:当前字符串第一位是’.’第二位是’e’,如”.e3”这样的形式则返回false;注意如 “1.e3”形式的字符串是合法的;
再判断最后一种情况,如果s[i]的下一位s[i + 1]是 “+”或”-“符号则需延伸判断s[i + 1]是否是字符串最后一位,如果 “+”、”-“出现在最后一位则返回false,如果不是就特殊处理使i ++,跳过 “+” “-“符号位;
6.除此之外的所有情况都返回false;
7.如果通过了以上所有判断(跳出循环),则说明字符串合法,返回true;
class Solution {
public:
bool isNumber(string s) {
int i = 0;
//对应1.
while (i < s.size() && s[i] == ' ') i ++ ;
int j = s.size() - 1;
while (j >= 0 && s[j] == ' ') j -- ;
//对应2.
if (i > j) return false;
s = s.substr(i, j - i + 1);
//对应3.
if (s[0] == '-' || s[0] == '+') s = s.substr(1);
//对应4.
if(s.empty() || s.size() == 1 && s[0] == '.')
return false;
int dot = 0, e = 0;
//对应5.
for(int i = 0; i < s.size(); i ++ ){
//对应5.1
if(s[i] >= '0' && s[i] <= '9')
continue;
//对应5.2
else if(s[i] == '.'){
dot ++ ;
if(e || dot > 1)return false;
}
//对应5.3
else if(s[i] == 'e' || s[i] == 'E'){
e ++ ;
//注意最后一种情况的特例
if(i + 1 == s.size() || i == 0 || e > 1 || i == 1 && s[0] == '.')return false;
if(s[i + 1] == '+' || s[i + 1] == '-'){
if(i + 2 == s.size())
return false;
//注意若合法则跳过正负号
i ++ ;
}
}
//对应6.
else
return false;
}
//对应7.
return true;
}
};
这题确实恶心