剑指 Offer 20. 表示数值的字符串
示例1:
示例2:
示例3:
示例4:
数据限制:
思路:
首先,我们先判断字符串前后可能存在的空格,将这些若干空格去掉,再判断剩下区间中是否存在空格,如果存在,则说明该字符串不符合规则,返回一个false,如果不存在,则我们得到一个预处理好的字符串
第一轮预处理之后,我们查找字符串中'.'
和e或E
的数量,如果有一个大于1,那么返回一个false
对于新的字符串,我们可以把他分成三部分,假设'.'
和e或E
都存在,那么将'.'
前面的那部分设为s1,将'.'
到e或E
的那部分设为s2,将e或E
后面的那部分设置为s3
之后,我们对s1,s2,s3进行判断,其中,s1和s3运行开头出现一个'+'
或'-'
,s2不允许,那么我们就先对s1和s3开头是否可能出现的'+'
和'-'
进行特判,如果存在,就将头一个元素去除,这样,我们就得到了新的字符串
对于处理之后的字符串,由于小说点的特性,我们允许s1和s2之中有一个为空(即""
),再进行特判,之后,我们判断三个字符串是否由存数字组成即可得到最终答案
上面讨论的是'.'
和e或E
都存在的情况,如果只存在一个,或都不存在,都要进行分别讨论
时间复杂度:O(n)
空间复杂度:O(n)
代码:
class Solution {
public boolean isNumber(String st) {
int len = st.length();
int l = 0, r = len - 1;
while (l < len && st.charAt(l) == ' ') l++;
while (r >= 0 && st.charAt(r) == ' ') r--;
for (int i = l; i <= r; i++){
if (st.charAt(i) == ' ') return false;
}
String s = "";
for (int i = l; i <= r; i++){
s += st.charAt(i);
}
len = s.length();
if (len == 0) return false;
l = -1; r = -1;
int num1 = 0, num2 = 0;
for (int i = 0; i < len; i++){
if (s.charAt(i) == '.'){
l = i;
num1++;
}
if (s.charAt(i) == 'e' || s.charAt(i) == 'E'){
r = i;
num2++;
}
}
if (num1 > 1 || num2 > 1) return false; // 两种特殊符号的个数有一个大于1
if (l == -1 && r == -1){ // 如果两个特殊符号都不存在
if (s.length() > 0 && (s.charAt(0) == '-' || s.charAt(0) == '+')) s = s.substring(1, s.length());
return su(s);
}
if (r == -1){ // 如果不存在e或E
String s1 = s.substring(0, l);
String s2 = s.substring(l + 1, len);
if (s1.length() > 0 && (s1.charAt(0) == '-' || s1.charAt(0) == '+')) s1 = s1.substring(1, s1.length());
if (s1.equals("") && s2.equals("")) return false;
if (s1.equals("")) return su(s2);
if (s2.equals("")) return su(s1);
return su(s1) && su(s2);
}
if (l == -1){ // 如果不存在 .
String s1 = s.substring(0, r);
String s3 = s.substring(r + 1, len);
if (s1.length() > 0 && (s1.charAt(0) == '-' || s1.charAt(0) == '+')) s1 = s1.substring(1, s1.length());
if (s3.length() > 0 && (s3.charAt(0) == '-' || s3.charAt(0) == '+')) s3 = s3.substring(1, s3.length());
if (s1.equals("") || s3.equals("")) return false;
return su(s1) && su(s3);
}
// 如果运行到这里,就证明两个特殊符号都出现了
if (l > r) return false; // 如果e或E 出现在 . 的前面
String s1 = s.substring(0, l);
String s2 = s.substring(l + 1, r);
String s3 = s.substring(r + 1, len);
if (s1.length() > 0 && (s1.charAt(0) == '-' || s1.charAt(0) == '+')) s1 = s1.substring(1, s1.length()); // 去掉前面可能存在的+-号
if (s3.length() > 0 && (s3.charAt(0) == '-' || s3.charAt(0) == '+')) s3 = s3.substring(1, s3.length());
if (s3.equals("")) return false; // 第三个字符串不能为空
if (s2.length() > 0 && (s2.charAt(0) == '+' || s2.charAt(0) == '-')) return false; // 第二个字符串不能出现+-号
if (s1.equals("") && s2.equals("")) return false; // s1 和 s2 可能出现的所有情况
if (s1.equals("")) return su(s2) && su(s3);
if (s2.equals("")) return su(s1) && su(s3);
return su(s1) && su(s2) && su(s3);
}
boolean su(String s){ // 用于判断一个字符串是否是纯数字组成
for (int i = 0; i < s.length(); i++){
if (s.charAt(i) < '0' || s.charAt(i) > '9'){
return false;
}
}
return true;
}
}