Valid Number

Valid Number

题目

题目链接:https://leetcode.com/problems/valid-number/

Validate if a given string can be interpreted as a decimal number.

Some examples:
"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false
"2e10" => true
" -90e3 " => true
" 1e" => false
"e3" => false
" 6e-1" => true
" 99e2.5 " => false
"53.5e93" => true
" --6 " => false
"-+3" => false
"95a54e53" => false

Note:
It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one. However, here is a list of characters that can be in a valid decimal number:

  • Numbers 0-9
  • Exponent - “e”
  • Positive/negative sign - “+”/"-"
  • Decimal point - “.”

Of course, the context of these characters also matters in the input.

分析

这道题其实就是给你一个字符串,让你判断这个字符串是不是一个实数。
那么,怎么表示的数才是一个实数呢?

首先去掉前后的空白字符(\t)。
剩下的子串中最前面可以有+或者是-号。然后是整数部分,小数点和小数部分。需要注意的是:正负号可有可无,只能有一个;整数,小数点和小数部分可以是下面任意一种形式,a.ba.a.b。不能是.ab其实就是ab其实就是a)。
上面那部分可以作为一个完整的实数表示了,也可以还有指数部分。指数部分需要与上面那部分一起出现(在它们后面),不能单独出现。
指数部分以e开头,接正负号,整数。需要注意的是在有指数部分的情况下:e必须有;正负号可有可无,只能有一个;整数必须有,可以是0,不能包含小数点。

这道题可以有下面三种解法:

  1. 使用Java中自带的Double.valueOf(String s)方法
    这算是一种偷懒的方法。直接利用已有的方法。
    当其尝试转换一个不是数的字符串时会抛出异常,我们可以捕获这个异常并且return false。否则return true
    但是需要注意的是,Double.valueOf方法在判断时,如果给出的字符串以D或者d结尾(表示double类型),或者是以f或者F结尾(表示float类型),或者指数以E表示(题目中是以e表示)时,也能正确解析。因此我们需要先判断上面的几种例外情况,然后再利用Double.valueOf方法。
    但是这种方法时间复杂度并不低。
  2. 使用正则表达式
    自己手写一个正则表达式,然后使用String.matches(String pattern)方法。
    最后的正则表达式如下:\\s[+-]?(?:[0-9]+(?:\\.[0-9]*)?|\\.[0-9]+)(?:e[+-]?[0-9]+)?\\s。需要注意的是,\s表示空白字符,再java中必须使用\\表示\,否则会将\s当做是转义字符。\.也同理,需要用\\.表示。
    这种方法时间复杂度很高,比第一种慢很多。
  3. 普通方法(遍历判断)
    从左到右遍历这个字符串。然后逐步利用上面的要求进行判断。下面的代码可以清晰地看到这个判断过程,此处不进行叙述。

代码如下

方法一

class Solution {
	public boolean isNumber(String s) {
    	if (s.contains("f") || s.contains("F") || s.contains("D") || s.contains("d") || s.contains("E")) {
			return false;
		}
    	try {
			Double.valueOf(s);
			return true;
		} catch (Exception e) {
			return false;
		}
	}
}

方法二

class Solution {
    public boolean isNumber(String s) {
        s = s.trim();
        // 这里先去除了s前后地空白字符,因此正则表达式前后不用加上 \\s 。
        // ?: 表示非捕获匹配。不影响匹配结果。为了不影响阅读,可以将其去掉
    	String pattern = "[+-]?(?:[0-9]+(?:\\.[0-9]*)?|\\.[0-9]+)(?:e[+-]?[0-9]+)?";
    	return s.matches(pattern);
    }
}

方法三

class Solution {
    public boolean isNumber(String s) {
    	
    	char[] values = s.toCharArray();
    	
    	int index = 0;
    	
    	boolean integer = false;  // 整数部分
    	boolean fraction = false;  // 小数部分
    	boolean blank = false;  // 中间是否有空白部分
    	boolean exponent = false;  // 指数
    	
    	// 跳过空白字符
    	while (index < values.length && (values[index] == ' ' || values[index] == '\t')) {
			index++;
		}
    	
    	if (index >= values.length) {
    		return false;
    	}
    	
    	// 正负号
    	if (index < values.length && (values[index] == '+' || values[index] == '-')) {
    		index++;
    	}
    	
    	if (index >= values.length) {
    		return false;
    	}
    	
    	// 整数部分
    	while (index < values.length && values[index] >= '0' && values[index] <= '9') {
			integer = true;  // 有整数部分
			index++;
		}
    	
    	// 小数点
    	if (index < values.length && values[index] == '.') {
    		index++;
    	}
    	
    	// 小数部分
    	while (index < values.length && values[index] >= '0' && values[index] <= '9') {
			fraction = true;
			index++;
		}
    	
    	// 没有整数也没有小数(小数点有没有都无所谓)
    	if (!integer && !fraction) {
    		return false;
    	}
    	
    	// 结尾部分的空白字符
    	while (index < values.length && (values[index] == ' ' || values[index] == '\t')) {
    		blank = true;
			index++;
		}
    	
    	// 到达末尾
    	if (index == values.length) {
    		return true;
    	} else if (blank) {
			return false;
		}
    	
    	// 指数e
    	if (values[index] == 'e' && index + 1 < values.length) {
    		index++;
    	} else {
			return false;
		}
    	
    	// 指数部分的正负号
    	if (values[index] == '+' || values[index] == '-') {
    		index++;
    	}
    	
    	// 指数
    	while (index < values.length && values[index] >= '0' && values[index] <= '9') {
    		exponent = true;
			index++;
		}
    	
    	// 没有指数
    	if (!exponent) {
    		return false;
    	}
    	// 结尾部分的空白字符
    	while (index < values.length && (values[index] == ' ' || values[index] == '\t')) {
			index++;
		}
    	
    	if (index >= values.length) {
    		return true;
    	} else {
			return false;
		}
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值