刷题笔记 剑指 Offer 20. 表示数值的字符串

难度:中等


请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。

数值(按顺序)可以分成以下几个部分:

  • 若干空格
  • 一个 小数 或者 整数
  • (可选) 一个 'e' 或 'E' ,后面跟着一个 整数
  • 若干空格

小数(按顺序)可以分成以下几个部分:

    (可选)一个符号字符('+' 或 '-')
    下述格式之一:

  • 至少一位数字,后面跟着一个点 '.'
  • 至少一位数字,后面跟着一个点 '.' ,后面再跟着至少一位数字
  • 一个点 '.' ,后面跟着至少一位数字

整数(按顺序)可以分成以下几个部分:

  • (可选)一个符号字符('+' 或 '-')
  • 至少一位数字

部分数值列举如下:

    ["+100", "5e2", "-123", "3.1416", "-1E-16", "0123"]

部分非数值列举如下:

    ["12e", "1a3.14", "1.2.3", "+-5", "12e+5.4"]

本题属于典型的字符串校验问题。

字符串校验问题不考察典型的数据结构或算法,而是考察考虑问题的周到程度。很多人并不喜欢这类问题,因为过程往往非常繁琐。

实际上,这种问题可以看做业务逻辑的一种抽象。在业务开发中,也经常需要碰见类似的情况,例如判断一个字符串是不是符合标准,因此这类问题还是有一定实际意义的。

【解】

字符串校验问题的核心在于归纳,要么归纳出所有不合条件的,剩下的都符合条件;要么直接归纳出所有符合条件的情况返回,这里采用方法一,归纳出所有不合条件的,剩下的就一定符合条件

首先,先对字符串做一些处理:

1) 去掉字符串左右两端的干扰空格

2) 如果有正负号,去掉正负号(把后面的内容当做一个无符号数看待)

3) 如果在上面两步结束以后,字符串长度为1,那这个字符一定要在0~9之间,否则不合条件

做完上面几步后,就可以根据归纳,分别对每一种情况做处理:

    1. '.'字符

        1) 字符串中只能有一个点字符

        2) 不能在E的后面;如果在E的前一位,那么它的前面必须有数字('.'不能在第一位)

    2. 'e' 或 'E'

        1) 字符串中只能有一个E或e字符

        2) 不能在最前面或最后面

    3. '+' 或 '-'

        1) 在去掉开头的正负号后,只能出现在E后一位,而且不能是整个字符串的最后一位

    4. '0' ~ '9'

        符合条件,continue

    5. 其它字符,不符合条件,直接返回false

在经过上面的归纳后,剩下的一定是符合条件的字符串

代码如下:

class Solution {
    public boolean isNumber(String s) {
// 去空格
        s = s.trim();
        if (s.equals("")) return false;
        // 有符号就去符号,如果去掉以后后面没有元素了,说明不符合条件,返回false
        if (s.charAt(0) == '+' || s.charAt(0) == '-') s = s.substring(1);
        if (s.equals("")) return false;
        // 前置工作完成,开始扫描字符串
        int length = s.length();
        if (length == 1 && (s.charAt(0) > '9' || s.charAt(0) < '0')) return false;
        HashMap<Character, Integer> map = new HashMap<>();
        for (int i = 0; i < length; i++) {
            char c = s.charAt(i);
            // 1) 如果是'.' 1.出现多个点,false; 2.在e后,false
            if (c == '.') {
                if (map.containsKey('.')) return false;
                if (map.containsKey('e')) return false;
                map.put('.', i);
            }
            // 2) 如果是'e'或'E' 1.出现多个e,false; 2.出现在最前或最后,false; 3.e前面有.且.是第一个元素,false
            else if (c == 'e' || c == 'E') {
                if (map.containsKey('e')) return false;
                if (i == 0 || i == length - 1) return false;
                if (map.containsKey('.') && map.get('.') + 1 == i && i == 1) return false;
                map.put('e', i);
            }
            // 3) 如果是'+'或'-' 只能在e后面,而且不能在最后
            else if (c == '+' || c == '-') {
                if (map.containsKey('e') && map.get('e') + 1 == i && i != length - 1) {
                    continue;
                } else {
                    return false;
                }
            }
            else if ('0' <= c && c <= '9') {
                continue;
            }
            else {
                return false;
            }
        }
        return true;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值