剑指Offer 20—表示数值的字符串

题目描述

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

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

  1. 若干空格
  2. 一个 小数 或者 整数
  3. (可选)一个 'e' 或 'E' ,后面跟着一个 整数
  4. 若干空格

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

  1. (可选)一个符号字符('+' 或 '-'
  2. 述格式之一:
    1. 至少一位数字,后面跟着一个点 '.'
    2. 至少一位数字,后面跟着一个点 '.' ,后面再跟着至少一位数字
    3. 一个点 '.' ,后面跟着至少一位数

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

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

部分数值列举如下:

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

部分非数值列举如下:

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

 

题目直达

力扣https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof/

解题思路

从题目描述中,我们可以知道,一个字符串如果是数值,它由:

若干空格、小数 /整数、e整数、若干空格

 组成。

按题目定义的格式,对字符串直接分段判断更直观。

主要算法流程为:

  • 去掉头尾空格,处理剩下部分。
  • 判断是否带e/E
    • 带,要求是整数或小数
    • 带,以e/E为分隔符,分为前后两部分,前面要求整数或小数,后面要求整数

C++代码实现

根据代码注释和上面的算法流程 ,很好理解。

// 判断是不是符号位,函数体少,建议使用内联函数。
static inline bool isSignChar(char c) 
{
    return c == '+' || c == '-';
}

//判断是不是数字
static inline bool isNumChar(char c)
{
    return c >= '0' && c <= '9';
}

// 判断是否整数
static bool isInteger(const char* s, int len) 
{
    //例如:+10,3
    if (len <= 0)
        return false;

    // 判断符号字符
    if (isSignChar(s[0]) && len > 1) 
    {
        ++s;
        --len;
    }	// 10,2

    for (int i = 0; i < len; ++i) 
    {
        if (!isNumChar(s[i])) //如果不是数字
            return false;
    }
    return true;
}

// 判断是否小数
static bool isDecimal(const char* s, int len) 
{
    // 例如 +15.5,+10.,+.5
    if (len <= 0)
        return false;

    if (isSignChar(s[0]) && len > 1) 
    {
        ++s;
        --len;
    }
	
    int dot_index = -1;
    for (int i = 0; i < len; ++i) 
    {
        if (s[i] == '.') 
        {
            if (dot_index == -1)
                dot_index = i;
            else //只能有一个.
                return false;
        } 
        else if (!isNumChar(s[i]))	//符号位之后,既不是. 也不是数字
            return false;
    }
    // 至少存在 '.' 和一个数字
    return dot_index >= 0 ? len > 1 : false;
}

class Solution 
{
public:
    bool isNumber(string s) 
    {
        const char* p = s.c_str();//string转char* 
        int len = s.length();
        // 跳过头尾空格
        const char* l = p, *r = p + len - 1;
        while (l <= r && *l == ' ') ++l;
        while (l <= r && *r == ' ') --r;
        // 全是空格或空字符串
        if (l > r) 
        {
            return false;
        }

        // 搜索 e/E
        const char* c = l;
        while (c <= r && *c != 'e' && *c != 'E')
            ++c;
        if (c < r) //这里 c必须小于r,因为如果有e,e后面必须是整数,c所处的位置代表的元素是e,c不能>=r了。 
        {
            // 有 e/E,后面跟整数
            return (isInteger(l, c - l) || isDecimal(l, c - l)) && isInteger(c + 1, r - c);
        } 
        else // c>=r了。
        {
            // 无 e/E。判断整个字符串是整数还是小数。
            return isInteger(l, r - l + 1) || isDecimal(l, r - l + 1);
        }
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心之所向便是光v

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值