#数据结构与算法学习笔记#剑指Offer51:表示数值的字符串 + 正则表达式(Java、C/C++)

234 篇文章 1 订阅
80 篇文章 0 订阅

2019.2.20     《剑指Offer》从零单刷个人笔记整理(66题全)目录传送门​​​​​​​

这道题实质上是一道逻辑题,需要把分类做到全面严谨。从最高位开始按位依次检查:

1.如果只有一位非数字字符,直接返回false。

2.若起始有正负号,跳过。

3.若是数字,继续前进。

4.若出现小数点,标记小数点已经出现(仅能出现一次),跳过并继续前进。(注意小数点之前可以没有数字,且小数点不能在末尾)

5.若出现科学计数法符号‘E’/‘e’,检查其余各位是否为纯数字,是则返回True。(‘E’/‘e’之后的数字如果有正负号要跳过)

6.其余情况导致循环未能结束,返回false。

7.循环顺利结束,返回True。

一些特殊的测试用例:

		char[] str0 = {'+', '1', '0'};
		char[] str1 = {'5', 'e', '2'};
		char[] str2 = {'-', '1', '2'};
		char[] str3 = {'3', '.', '1', '4'};
		char[] str4 = {'-', '1', 'E', '-', '1', '6'};
		char[] str5 = {'1', '1', 'e'};
		char[] str6 = {'1', 'a', '3', '.', '1', '4'};
		char[] str7 = {'1', '.', '2', '.', '1'};
		char[] str8 = {'+', '-', '5'};
		char[] str9 = {'-', '1', 'E', '-', '1', '.', '6'};
		char[] str10 = {'1', '.', '1', 'e', '+', '1', '6'};	//科学计数法前可以有小数点
		char[] str11 = {'.', '1', 'e', '+', '1', '6'};		//小数点前可以没有数字
		char[] str12 = {'1', '.'};			        //小数点不能结尾

 另外,这道题还有捷径。如果对正则表达式比较熟悉,可以直接用正则表达式一键解决:

return string.matches("[\\+\\-]?\\d*(\\.\\d+)?([eE][\\+\\-]?\\d+)?");

 [\\+\\-]?                  ->       正或负符号出现与否
\\d*                         ->       整数部分是否出现,d表示整数,*表示任意次
(\\.\\d+)?                 ->       如果出现小数点,那么小数点后面必须有数字,+表示大于等于1次
([eE][\\+\\-]?\\d+)?  ->       如果存在指数部分,那么e或E肯定出现,+或-可以不出现, 紧接着必须跟着整数


题目描述

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。


Java实现:

/**
 * 
 * @author ChopinXBP
 * 请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
 * 例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。
 * 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。
 * 
 */

public class IsNumeric_52 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		char[] str0 = {'+', '1', '0'};
		char[] str1 = {'5', 'e', '2'};
		char[] str2 = {'-', '1', '2'};
		char[] str3 = {'3', '.', '1', '4'};
		char[] str4 = {'-', '1', 'E', '-', '1', '6'};
		char[] str5 = {'1', '1', 'e'};
		char[] str6 = {'1', 'a', '3', '.', '1', '4'};
		char[] str7 = {'1', '.', '2', '.', '1'};
		char[] str8 = {'+', '-', '5'};
		char[] str9 = {'-', '1', 'E', '-', '1', '.', '6'};
		char[] str10 = {'1', '.', '1', 'e', '+', '1', '6'};	//科学计数法前可以有小数点
		char[] str11 = {'.', '1', 'e', '+', '1', '6'};		//小数点前可以没有数字
		char[] str12 = {'1', '.'};							//小数点不能结尾
		System.out.println(isNumeric(str0));
		System.out.println(isNumeric(str1));
		System.out.println(isNumeric(str2));
		System.out.println(isNumeric(str3));
		System.out.println(isNumeric(str4));
		System.out.println(isNumeric(str5));
		System.out.println(isNumeric(str6));
		System.out.println(isNumeric(str7));
		System.out.println(isNumeric(str8));
		System.out.println(isNumeric(str9));
		System.out.println(isNumeric(str10));
		System.out.println(isNumeric(str11));
		System.out.println(isNumeric(str12));
	}

	//分类方法
    public static boolean isNumeric(char[] str) {
        if(str == null)return false;
        int length = str.length;
        //只有一位非数字返回false
        if(length == 1 && !isNum(str[0])) return false;
        
        int idx = 0;
        //跳过起始的正负号
        if(str[0] == '+' || str[0] == '-') idx++;
        
        boolean hasPoint = false;	//记录是否出现过小数点
        for(int i = idx; i < length; i++) {
        	//若该位是数字,继续前进
        	if(isNum(str[i])) {
        		continue;
        	}
        	//若第一次出现小数点(可以在起始不能在末尾),标记小数点已出现,继续前进
        	else if(str[i] == '.' && i != length - 1 && !hasPoint) {
        		hasPoint = true;
        		continue;
        	}
        	//若出现e/E,则检查其余数字是否全为数字(可以带正负号)
        	else if((str[i] == 'e' || str[i] == 'E') && i != idx && i != length - 1) {
        		if((str[i + 1] == '+' || str[i + 1] == '-') && i != length - 2) i++;
        		return isWholeNum(str, i + 1);
        	}
        	else {
        		return false;
        	}
        }
        
        return true;
    }
    
    public static boolean isNum(char word) {
    	if(word >= '0' && word <= '9') return true;
    	return false;
    }
    
    //是否从idx之后全是数字
    public static boolean isWholeNum(char[] str, int idx) {
    	for(int i = idx; i < str.length; i++) {
    		if(!isNum(str[i])) return false;
    	}
    	return true;
    }
    
    //正则表达式法
	/*
	 * [\\+\\-]? 			-> 正或负符号出现与否
	 * \\d* 				-> 整数部分是否出现,d表示整数,*表示任意次
	 * (\\.\\d+)? 			-> 如果出现小数点,那么小数点后面必须有数字,+表示大于等于1次
	 * ([eE][\\+\\-]?\\d+)? -> 如果存在指数部分,那么e或E肯定出现,+或-可以不出现, 紧接着必须跟着整数
	 */
	public class Solution {
		public boolean isNumeric(char[] str) {
			String string = String.valueOf(str);
			return string.matches("[\\+\\-]?\\d*(\\.\\d+)?([eE][\\+\\-]?\\d+)?");
		}
	}
}

C++实现示例:

class Solution {
public:
    bool isNumeric(char* str) {
        // 标记符号、小数点、e是否出现过
        bool sign = false, decimal = false, hasE = false;
        for (int i = 0; i < strlen(str); i++) {
            if (str[i] == 'e' || str[i] == 'E') {
                if (i == strlen(str)-1) return false; // e后面一定要接数字
                if (hasE) return false;  // 不能同时存在两个e
                hasE = true;
            } else if (str[i] == '+' || str[i] == '-') {
                // 第二次出现+-符号,则必须紧接在e之后
                if (sign && str[i-1] != 'e' && str[i-1] != 'E') return false;
                // 第一次出现+-符号,且不是在字符串开头,则也必须紧接在e之后
                if (!sign && i > 0 && str[i-1] != 'e' && str[i-1] != 'E') return false;
                sign = true;
            } else if (str[i] == '.') {
              // e后面不能接小数点,小数点不能出现两次
                if (hasE || decimal) return false;
                decimal = true;
            } else if (str[i] < '0' || str[i] > '9') // 不合法字符
                return false;
        }
        return true;
    }
};

#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值