Day26-字符与数字转换_剑指Offer

表示数值的字符串


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;
  }
}


我的博客:Day26_字符与数字_剑指Offer | IT蛋的个人博客 (xcscx.github.io)

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
IT蛋
下载 APP