这是我参与更文挑战的第2天,活动详情查看: 更文挑战
题目
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
数值(按顺序)可以分成以下几个部分:
- 若干空格
- 一个 小数 或者 整数
- (可选)一个 ‘e’ 或 ‘E’ ,后面跟着一个 整数
- 若干空格
小数(按顺序)可以分成以下几个部分:
- (可选)一个符号字符(’+’ 或 ‘-‘)
- 下述格式之一:
- 至少一位数字,后面跟着一个点 ‘.’
- 至少一位数字,后面跟着一个点 ‘.’ ,后面再跟着至少一位数字
- 一个点 ‘.’ ,后面跟着至少一位数字
整数(按顺序)可以分成以下几个部分:
- (可选)一个符号字符(’+’ 或 ‘-‘)
- 至少一位数字
部分数值列举如下:
[“+100”, “5e2”, “-123”, “3.1416”, “-1E-16”, “0123”]
部分非数值列举如下:
[“12e”, “1a3.14”, “1.2.3”, “+-5”, “12e+5.4”]
来源:力扣(LeetCode)
思路
本题有多种解法:「正则」、「DFA」、「模拟」,这边用比较容易理解的字符串模拟的方法
1.这道题和leetcode的第65几乎完全一样只是因为多了一种数值部分的情况(若干空格)所以刚开始需要调用trim()方法去掉前后的空格
2.把字符串以e(E)作为中心分成左右两个部分,根据题目所给条件可以知道,e(E)前面的部分既可以是整数也可以是小数,e(E)后面的部分只能是整数
3.实现一个isChecked方法判断字符串的合理性
- +或者-只能出现在第一个位置
- .只能出现一次
- 至少出现一次数字
public boolean isNumber(String s) {
s = s.trim();//去掉前后的空格
char[] cs = s.toCharArray();
int n = cs.length;
int idx = -1;
//1.找到第一个e或者E的位置
for (int i = 0; i < cs.length; i++) {
if (cs[i] == 'e' || cs[i] == 'E') {
if (idx != -1) {
return false; //说明出现了两次e(E)
} else {
idx = i;
}
}
}
boolean ans = true;
//在这个e或者E作为中心作为划分
if (idx == -1) { //如果idx=-1说明没有E和e e(E)后面必须跟整数,前面既可以是小数也可以是整数
ans &= isChecked(cs, 0, n - 1, false);
} else {
ans &= isChecked(cs, 0, idx - 1, false);
ans &= isChecked(cs, idx + 1, n - 1, true);
}
return ans;
}
public boolean isChecked(char[] cs, int start, int end, boolean mustInt) {
if (start > end) return false;
boolean point = false;
boolean hasNum = false;
//1.如果第一个位置是+-号
if (cs[start] == '+' || cs[start] == '-') start++;
for (int i = start; i <= end; i++) {
if (cs[i] >= '0' && cs[i] <= '9') {
hasNum = true;
} else if (cs[i] == '.' && !point) {
if (mustInt) return false; //如果必须是整数的话不能出现小数点
point = true;
} else {
return false;
}
}
return hasNum;
}
复制代码
时间复杂度
O(N)
额外空间复杂度
O(N)用到了cs数组存储,当然如果使用charAt方法可以把额外空间复杂度降为O(1)
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END