Problem:
Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.
Validate if a given string is numeric.
Some examples:
"0"
=> true
" 0.1 "
=> true
"abc"
=> false
"1 a"
=> false
"2e10"
=> true
Solution 1:My Solution
算法思路:
1.用if语句分情况判断:
a.去掉字符串头尾的空格,比如str=" 123 ",转变为str2="123";
b.判断str2是否是空格,如果是则return false;
c.如果首字符是+,则去掉+,继续判断;
d.如果首字符是e或E,则return false;
e.判断字符串中是否存在空格或+或-,如果存在空格,则return false;
如果存在+或1,则判断是否是e+或e-的组合;
f.判断是否存在除e或E以外的字母(如s),以及除+或-以外的字符(如*),如果存在,则return false;
g.判断e后面是否存在'.',如果存在,则return false;
h.判断string是否以.e开头,如果是,则return false;
i. 判断是否为"+."或"-."或".",如果是,则return false.
j. 否则以上情况不满足,则return true.
使用内建函数有:substr()、find()、find_last_of()、find_first_of()、isalpha()、ispunct()等
<pre name="code" class="cpp"> bool isNumber(const char *s)
{
string str(s);
/*1:去除头尾的空格*/
size_t start = str.find_first_not_of(' ');
if(start == string::npos)//如果字符为空格
return false;
size_t end = str.find_last_not_of(' ');
string str2 = str.substr(start, end - start + 1);
// cout<<"str2 is "<<str2<<endl;
if(str2[0] == '+')
str2 = str2.substr(1, str2.length() - 1);
if(str2[0] == 'e' || str2[0] == 'E')
{
// cout<<str<<" is e"<<endl;
return false;
}
/*2:判断字符串中是否存在空格和'-'*/
size_t len = str2.length();
for(int i = 0 ; i < len; i++)
{
if(str2[i] == ' ')
{
// cout<<"Some blanks exist in this string:"<<str<<endl;
return false;
}
if(i >= 1)
{
if(str2[i] == '+' || str2[i] == '-')
{
if(str2[i - 1] != 'e')
return false;
}
}
}
/*3:判断字符串中是否存在e和E以外的字母或者标点符号,以及是否存在多个e、多个'.'*/
int e_num = 0;
int dot_num = 0;
bool alpha = true;
for(int i = 0; i < len; i++)
{
char ch = str2[i];
if(isalpha(ch) && ch != 'e' && ch != 'E' || ispunct(ch) && ch != '.' && ch != '-' && ch != '+')
{
// cout<<"Some alphas or punctuation exist in this string:"<<str<<endl;
alpha = false;
}
if(ch == 'e' || ch == 'E')
e_num ++;
if(ch == '.')
dot_num ++;
}
if(!alpha || e_num >= 2 || dot_num >= 2)
return false;
/*5判断e后面是否有'.',如果有,则返回false*/
size_t e_index = str2.find_last_of('e');
size_t dot_index = str2.find_last_of('.');
if(e_index != string::npos && dot_index != string::npos)
{
if(e_index < dot_index)
return false;
}
/*6判断string是否是0e,如果是,则返回false*/
if(len >= 2)
{
if(str2.substr(0, 2) == ".e")
return false;
}
if(str2 == ".")
return false;
if(str2[len - 1] == 'e' || str2[len - 1] == 'E' || str2[len - 1] == '+' || str2[len - 1] == '-')
return false;
if(str2 == "+." || str2 == "-.")
return false;
if(str2.substr(0, 2) == "-e")
return false;
return true;
}
Solution 2:有限状态自动机(DFA)转自网友
算法思路:
It's just some states changes depend on inputs only.
There 8 state in my states in my DFA. Below is my DFA transition diagram.
There are 5 kind of inputs in my DFA:
digit : number 0-9 for
+,- : operator + or -(negative or positive)
exp: e
dot: .
other: you can return false Immediately
4 final States in my DFA transition diagram : s2, s6, s7, s8
If the state change to final state at last, return true.
s2 can accept digits only : +1 -23432 123 and etc
s5 can accept exp expression: +2.4e+12 3e9 and etc
s6 can accept decimals end with dot: 1. -42. and etc (careful, what if there exist only on dot)
s7 can accept decimals: +12.23, 87., 132
It is clear how DFA works in my pictures. We just need to handle the inputs, and update the state according to DFA.
bool isNumber(string str) {
int state=0, flag=0; // flag to judge the special case "."
while(str[0]==' ') str.erase(0,1);//delete the prefix whitespace
while(str[str.length()-1]==' ') str.erase(str.length()-1, 1);//delete the suffix whitespace
for(int i=0; i<str.length(); i++){
if('0'<=str[i] && str[i]<='9'){
flag=1;
if(state<=2) state=2;
else state=(state<=5)?5:7;
}
else if('+'==str[i] || '-'==str[i]){
if(state==0 || state==3) state++;
else return false;
}
else if('.'==str[i]){
if(state<=2) state=6;
else return false;
}
else if('e'==str[i]){
if(flag&&(state==2 || state==6 || state==7)) state=3;
else return false;
}
else return false;
}
return (state==2 || state==5 || (flag&&state==6) || state==7);
}
心得总结
1.find_first_of()函数:可以查找一个字符串中的所有是否存在,而不限于一个字符;