算法题:剑指 Offer 20. 表示数值的字符串(题目+思路+代码+注释)时空 O(N) O(N) 5ms击败44%、33%用户

在这里插入图片描述

题目

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

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

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

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

(可选)一个符号字符(’+’ 或 ‘-’)
至少一位数字
部分数值列举如下:

["+100", “5e2”, “-123”, “3.1416”, “-1E-16”, “0123”]
部分非数值列举如下:

[“12e”, “1a3.14”, “1.2.3”, “±5”, “12e+5.4”]

示例 1:

输入:s = “0”
输出:true
示例 2:

输入:s = “e”
输出:false
示例 3:

输入:s = “.”
输出:false
示例 4:

输入:s = " .1 "
输出:true

提示:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

一开始想过用一个列表存下一个允许出现的字符,然后根据不断出现的字符修改接下来允许的字符列表,保存状态,类似于状态机,但是后面想了下,我直接把这个分解成几个小判断函数然后分类讨论下岂不是更简单写出了
题目中说前后可能有空格,那就搞个函数来删除前后空格

	/**
     * 去除前后连续空格
     * @param sb
     * @return
     */
    public StringBuilder deleteBlank(StringBuilder sb){
        //
        int i = 0;
        for (int len = sb.length(); i < len;i++){
            if (sb.charAt(i) != ' '){
                break;
            }
        }
        if (i > 0){
            //删除前面的空格
            sb.delete(0,i);
        }
        i = sb.length()-1;
        for (; i >= 0;i--){
            if (sb.charAt(i) != ' '){
                break;
            }
        }
        if (i < sb.length()-1){
            sb.delete(i+1,sb.length());
        }
        return sb;
    }

于是乎我需要一个判断字符是不是数字的函数

	/**
	* 这个字符是不是数字
	* @param c
	* @return
	*/
	public boolean isDigitChar(char c){
	   return c >= '0' && c <= '9';
	}

需要一个判断字符串是不是整数的函数

/**
     * 检查是否是整数
     * @param s
     * @return
     */
    public boolean isInteger(String s){
        int left = 0;
        if (s.length() > 0 && (s.charAt(0) == '+' || s.charAt(0) == '-')){
            left = 1;
        }
        if (s.length() > left){
            for (int i = left,len = s.length();i < len;i++){
                if (!isDigitChar(s.charAt(i))){
                    return false;
                }
            }
            return true;
        }
        return false;
    }

需要一个判断字符串是不是小数的函数

/**
     * 判断是不是个小数
     * @param s
     * @return
     */
    public boolean isFloat(String s){
        int left = 0;
        //去掉符号位
        if (s.length() > 0 && (s.charAt(0) == '+' || s.charAt(0) == '-')){
            left = 1;
        }
        if (s.length() > left){
            if (s.charAt(left) == '.'){
                // .开头
                if (s.length() == left + 1){
                    return false;
                }
                for (int i = left + 1,len = s.length(); i < len;i++){
                    if (!isDigitChar(s.charAt(i))){
                        return false;
                    }
                }
                return true;
            }else {
                boolean dot = false;
                for (int i = left,len = s.length();i < len;i++){
                    char c = s.charAt(i);
                    if (c == '.' && !dot){
                        dot = true;
                        continue;
                    }else if (!isDigitChar(c)){
                        return false;
                    }
                }
                return true;
            }
        }
        return false;
    }

基本的函数有了那我们开始主体工程
第一步:把E变成小写e,方便后续处理,对e计数,多了e则返回false
第二步:去除前后连续空格
第三步:分类讨论,有e还是没有
第四步:有e的前面必须是小数或者整数,e后面必须是个整数
第五步:没有e的就必须是个小数或者整数
检查完成

代码

public boolean isNumber(String s) {
        StringBuilder sb = new StringBuilder(s);
        //大E变小e,并且最多一个e
        int count = 0;
        for (int i = 0,len = s.length();i < len;i++){
            if (sb.charAt(i) == 'E'){
                sb.setCharAt(i,'e');
                count++;
            }else if (sb.charAt(i) == 'e'){
                count++;
            }

        }
        if (count > 1){
            return false;
        }
        //去除空格
        deleteBlank(sb);
        s = sb.toString();
        if (sb.length() > 0){
            //是否有e,有的话拆分
            if (s.indexOf("e") != -1){
                //有e,切割
                String[] pieces = s.split("e");
                //前面必须是小数、整数,后面必须是整数
                if (pieces.length == 2 && (isInteger(pieces[0]) || isFloat(pieces[0])) && isInteger(pieces[1])){
                    return true;
                }
            }else {
                return isInteger(s) || isFloat(s);
            }
        }
        return false;
    }

    /**
     * 去除前后连续空格
     * @param sb
     * @return
     */
    public StringBuilder deleteBlank(StringBuilder sb){
        //
        int i = 0;
        for (int len = sb.length(); i < len;i++){
            if (sb.charAt(i) != ' '){
                break;
            }
        }
        if (i > 0){
            //删除前面的空格
            sb.delete(0,i);
        }
        i = sb.length()-1;
        for (; i >= 0;i--){
            if (sb.charAt(i) != ' '){
                break;
            }
        }
        if (i < sb.length()-1){
            sb.delete(i+1,sb.length());
        }
        return sb;
    }

    /**
     * 判断是不是个小数
     * @param s
     * @return
     */
    public boolean isFloat(String s){
        int left = 0;
        if (s.length() > 0 && (s.charAt(0) == '+' || s.charAt(0) == '-')){
            left = 1;
        }
        if (s.length() > left){
            if (s.charAt(left) == '.'){
                // .开头
                if (s.length() == left + 1){
                    return false;
                }
                for (int i = left + 1,len = s.length(); i < len;i++){
                    if (!isDigitChar(s.charAt(i))){
                        return false;
                    }
                }
                return true;
            }else {
                boolean dot = false;
                for (int i = left,len = s.length();i < len;i++){
                    char c = s.charAt(i);
                    if (c == '.' && !dot){
                        dot = true;
                        continue;
                    }else if (!isDigitChar(c)){
                        return false;
                    }
                }
                return true;
            }
        }
        return false;
    }
    /**
     * 检查是否是整数
     * @param s
     * @return
     */
    public boolean isInteger(String s){
        int left = 0;
        if (s.length() > 0 && (s.charAt(0) == '+' || s.charAt(0) == '-')){
            left = 1;
        }
        if (s.length() > left){
            for (int i = left,len = s.length();i < len;i++){
                if (!isDigitChar(s.charAt(i))){
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    /**
     * 这个字符是不是数字
     * @param c
     * @return
     */
    public boolean isDigitChar(char c){
        return c >= '0' && c <= '9';
    }
posted @ 2021-09-02 14:45  HumorChen99  阅读(1)  评论(0编辑  收藏  举报  来源