表示数值的字符串

medium 原题连接:表示数值的字符串

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

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

若干空格
一个 小数 或者 整数
(可选)一个 ‘e’ 或 ‘E’ ,后面跟着一个 整数
若干空格
小数(按顺序)可以分成以下几个部分:

(可选)一个符号字符(’+’ 或 ‘-‘)
下述格式之一:
至少一位数字,后面跟着一个点 ‘.’
至少一位数字,后面跟着一个点 ‘.’ ,后面再跟着至少一位数字
一个点 ‘.’ ,后面跟着至少一位数字
整数(按顺序)

可以分成以下几个部分:

(可选)一个符号字符(’+’ 或 ‘-‘)至少一位数字
部分数值列举:[“+100”, “5e2”, “-123”, “3.1416”, “-1E-16”, “0123”]

部分非数值列举:[“12e”, “1a3.14”, “1.2.3”, “+-5”, “12e+5.4”]

示例:

输入:s = "0"
输出:true
输入:s = "e"
输出:false
输入:s = "."
输出:false
输入:s = "    .1  "
输出:true

提示:

  1. 1 <= s.length <= 20
  2. s 仅含英文字母(大写和小写),数字(0-9),加号 '+' ,减号 '-' ,空格 ' ' 或者点 '.'

解题思路

一个包含全部可能的最大目标大致可以分为:

空格 正负 数字 小数点 数字 e/E 正负 数字 空格

从前到后依次划分部分进行检验:

  1. 删除前后空格
  2. 判断首字节是否为+-
  3. 依据E/e拆分为两个部分
  4. 前者判断是否由小数点,拆为两个部分
  5. 3中剩下的部分,4中的两个部分,检测是否为纯数字

注:允许4的前半部分为空

Java代码

class Solution {
    public boolean isNumber(String s) {
        // 空格 正负 数字 小数点 数字 e/E 正负 数字 空格
        // 1.将s删去前后空格,判断charAt(0)是否是正负号
        s = s.trim();
        if(s.length() == 0) return false;
        if(s.charAt(0) == '+' || s.charAt(0) == '-') s = s.substring(1);
        
        // 2.将剩余string依据e/E划分为两个部分,如果第二部分长度不为零,判断charAt(0)是否为符号
        s = s.replace('E','e');
        if(s.indexOf('e') >= 0) {
            int index = s.indexOf('e');
            String firstStr = s.substring(0,index);
            String secondStr = s.substring(index+1);
            if(secondStr.length() > 0) {
                if(secondStr.charAt(0) == '+' || secondStr.charAt(0) == '-') secondStr = secondStr.substring(1);
            }
            return isNum(firstStr) && isInteger(secondStr);
        }
        return isNum(s);
    }
    
    // 3.由2得到的两个字符,前者做数字判断(可为小数),后者做整数判断
    // 判断是否为整数(不可以为小数)
    public boolean isInteger(String str) {
        if(str == "") return false;
        for(char a : str.toCharArray()) {
            if(a < '0' || a > '9') return false;
        }
        return true;
    }

    // 判断是否为数(可以为小数)
    public boolean isNum(String str) {
        if(str.indexOf('.') >= 0) {
            int index = str.indexOf('.');
            String firstStr = str.substring(0,index);
            String secondStr = str.substring(index+1);
            if(firstStr.length() >0 && secondStr.length() >0) {
                return isInteger(firstStr) && isInteger(secondStr);
            }else if(secondStr.length() >0) {
                return isInteger(secondStr);
            }else {
                return isInteger(firstStr);
            }
        }
        return isInteger(str);
    }
}

把字符串转换成整数

medium 原题连接: 把字符串转换成整数

写一个函数 StrToInt,实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。

首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。

当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。

该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。

注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。

在任何情况下,若函数不能进行有效的转换时,请返回 0。

说明:

假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−2^31, 2^31 − 1]。如果数值超过这个范围,请返回 INT_MAX (2^31 − 1) 或 INT_MIN (−2^31)

示例:

输入: "42"
输出: 42
输入: "   -42"
输出: -42
解释: 第一个非空白字符为 '-', 它是一个负号。
     我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
输入: "4193 with words"
输出: 4193
输入: "words and 987"
输出: 0
解释: 第一个非空字符是 'w', 但它不是数字或正、负号。
     因此无法执行有效的转换。
输入: "-91283472332"
输出: -2147483648
解释: 数字 "-91283472332" 超过 32 位有符号整数范围。 
     因此返回 INT_MIN (−231) 。

解题思路

和第一题有些类似,删除空格,判断符号,遇到字母就跳出

需要注意的是,如果第一个字符是符号,数字需要从下标为1的地方开始读,如果没有符号,则从0开始读

为了避免超过int类型的最大值,可以在循环中判断,是否即将超过最大值(因为每次记录结果是将ans= ans*10+new)

所以先判断是否依据超过了int最大值的十分之一(否则接下来进行*10运算会超过最大值)

又或者恰好为2147483648、 2147483649,刚好超过一两位,所以在ans已经相等于int最大值的十分之一时判断最后一位的值是否大于7

Java代码

class Solution {
    public int strToInt(String str) {
        // 1.删去str前后端的空格,并判断charAt(0)是否为符号,做记录(符号sign与数字开始位i)
        str = str.trim();
        if(str.length() == 0) return 0;
        int sign = 1, index = 1;
        if(str.charAt(0) == '-') {
            sign = -1;
        }else if(str.charAt(0) != '+'){
            index = 0;
        }
        int ans = 0, max = Integer.MAX_VALUE/10;
        // 2.循环对数每一位做判断:
        for(; index < str.length(); index++) {
            // 3.弹出条件之一:遇到不是数字的数,break
            if(str.charAt(index)<'0' || str.charAt(index)>'9') break;
            // 4.弹出条件之二:已经超过最大值(符号已经记录,单纯看数值大小)
            if(ans>max || (ans==max && str.charAt(index)>'7')) 
                return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
            ans = ans*10+(str.charAt(index)-'0');
        }
        return ans*sign;
    }
}