一、题目描述
有效数字(按顺序)可以分成以下几个部分:
1. 一个 小数 或者 整数
2. (可选)一个 'e'
或 'E'
,后面跟着一个 整数
小数(按顺序)可以分成以下几个部分:
1. (可选)一个符号字符('+'
或 '-'
)
2. 下述格式之一:
- 至少一位数字,后面跟着一个点
'.'
- 至少一位数字,后面跟着一个点
'.'
,后面再跟着至少一位数字 - 一个点
'.'
,后面跟着至少一位数字
整数(按顺序)可以分成以下几个部分:
1. (可选)一个符号字符('+'
或 '-'
)
2. 至少一位数字
部分有效数字列举如下:["2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-123.456e789"]
部分无效数字列举如下:["abc", "1a", "1e", "e3", "99e2.5", "--6", "-+3", "95a54e53"]
给你一个字符串 s
,如果 s
是一个 有效数字 ,请返回 true
。
示例 1:
输入:s = "0" 输出:true
示例 2:
输入:s = "e" 输出:false
示例 3:
输入:s = "." 输出:false
提示:
1 <= s.length <= 20
s
仅含英文字母(大写和小写),数字(0-9
),加号'+'
,减号'-'
,或者点'.'
。
二、解题思路
- 首先,我们需要定义一些标志来记录字符串中的不同部分,例如是否有过数字出现、是否有小数点、是否有指数部分等。
- 遍历字符串,根据当前字符的类型,更新相应的标志,并且根据标志的状态来判断字符串是否符合有效数字的规则。
- 对于整数部分,我们需要至少有一个数字。
- 对于小数部分,我们需要有一个数字后跟一个小数点,并且点后至少有一个数字。
- 对于指数部分,我们需要有 'e' 或 'E' 后面跟随至少一个数字,并且整个指数部分是可选的。
- 在遍历过程中,我们需要处理一些特殊情况,例如连续的数字、点号等。
三、具体代码
public class Solution {public boolean isNumber(String s) {// 定义一些标志位boolean hasDigit = false; // 是否有数字出现boolean hasDecimal = false; // 是否有小数点boolean hasExp = false; // 是否有指数部分// 遍历字符串for (int i = 0; i < s.length(); i++) {char c = s.charAt(i);if (Character.isDigit(c)) {// 如果是数字,重置hasExp为false,并且至少有一个数字出现hasDigit = true;hasExp = false;} else if (c == '.') {// 如果是小数点,需要之前有数字,并且之后还需要有数字if (!hasDigit || hasDecimal) {return false; // 之前没有数字或者已经有小数点了,不是有效数字}hasDecimal = true;} else if (c == 'e' || c == 'E') {// 如果是指数部分,需要之前有数字,并且之后都是数字if (!hasDigit || hasExp) {return false; // 之前没有数字或者已经有指数部分了,不是有效数字}hasExp = true;hasDigit = false; // 重置hasDigit为false,因为我们需要重新验证后面的数字} else if (c == '+' || c == '-') {// 符号只允许出现在数字之前if (i != 0 || (i == 0 && !hasDigit)) {return false; // 符号出现在中间或者开头但没有数字,不是有效数字}} else {// 其他字符都不是有效数字的一部分return false;}}// 根据标志位来判断是否是有效数字return hasDigit && (!hasDecimal || hasExp);}
}
四、时间复杂度和空间复杂度
1. 时间复杂度
- 该算法的主要操作是一个遍历字符串的过程,遍历的复杂度是 O(n),其中 n 是字符串 s 的长度。
- 在遍历过程中,所做的操作(如字符判断、标志更新等)都是常数时间操作。
- 因此,整个函数的时间复杂度是 O(n)。
2. 空间复杂度
- 该算法中使用了固定的几个布尔变量来记录状态,这些变量的空间需求不随输入字符串的长度变化。
- 因此,整个函数的空间复杂度是 O(1)。
五、总结知识点
-
字符串遍历:通过
for
循环对字符串中的每个字符进行遍历,这是处理字符串问题中常见的方法。 -
字符判断:使用
Character.isDigit(c)
方法来判断当前字符是否为数字字符,这是处理数字相关字符串问题时的基础操作。 -
标志位:定义了几个布尔变量(
hasDigit
,hasDecimal
,hasExp
)作为标志位,用来追踪字符串中是否出现了数字、小数点和指数部分。这是处理复杂字符串匹配问题时常用的技巧,通过标志位来记录字符串的某些属性或状态。 -
逻辑判断:在遍历过程中,使用了一系列的条件判断来确定当前字符是否符合有效数字的规则。例如,检查小数点前后是否有数字,检查指数部分是否正确等。
-
特殊情况处理:代码中特别处理了符号字符('+', '-')的位置,确保它们只出现在数字的前面,且前面必须有数字。
-
返回值:根据标志位的最终状态来决定返回
true
或false
,这是判断类型问题的常见做法。 -
边界条件:代码中考虑了字符串为空或者不包含任何数字的情况,这些边界条件的处理对于确保算法的正确性非常重要。
-
错误处理:代码中通过返回
false
来处理不合法的输入,这是错误处理的一种简单有效的方法。
以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。