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

20.表示数值的字符串

题目

官方地址
剑指Offer 20.表示数值的字符串_第1张图片

代码(正则表达式)

public boolean isNumeric (String str) {
    if (str == null || str.length() == 0)
        return false;
    return new String(str).matches("[+-]?\\d*(\\.\\d+)?([eE][+-]?\\d+)?");
}

在给定的代码中,matches() 方法被用于判断一个字符串是否表示一个数值。下面是对该方法的详细解释:

if (str == null || str.length() == 0):首先,代码检查输入的字符串 str 是否为 null 或者长度为 0。如果是,表示字符串为空,无法进行数值判断,因此返回 false。

new String(str):代码创建了一个新的字符串对象,目的是为了调用 matches() 方法。这里的目的是确保 matches() 方法被调用。

matches("[+-]?\\d*(\\.\\d+)?([eE][+-]?\\d+)?"):该代码使用正则表达式来判断字符串是否匹配数值的模式。

  1. [±]?:表示正负号可选,即可有可无。 \d*:表示 0 个或多个数字。
  2. (\.\d+)?:表示小数部分,其中 \.表示小数点,\d+ 表示一个或多个数字。整个部分可选,表示小数部分可有可无。
  3. ([eE][±]?\d+)?:表示指数部分,其中[eE] 表示指数符号,[±]? 表示正负号可选,\d+ 表示一个或多个数字。整个部分可选,表示指数部分可有可无。

题解

class Solution {
    private int currentIndex;
    public boolean isNumber(String s) {
        s = s.trim();
        int n = s.length();
        if (n == 0) {
            return false;
        }
        currentIndex = 0;
        boolean numeric = scanInteger(s);
        // 如果出现'.',接下来是数字的小数部分
        if (currentIndex < n && s.charAt(currentIndex) == '.') {
            currentIndex++;
            // 下面一行代码用||的原因:
            // 1. 小数可以没有整数部分,例如.123等于0.123;
            // 2. 小数点后面可以没有数字,例如233.等于233.0;
            // 3. 当然小数点前面和后面可以有数字,例如233.666
            numeric = scanUsignedInteger(s) || numeric;
        }

        // 如果出现'e'或者'E',接下来跟着的是数字的指数部分
        if (currentIndex < n && (s.charAt(currentIndex) == 'e' || s.charAt(currentIndex) == 'E')) {
            currentIndex++;
            // 下面一行代码用&&的原因:
            // 1. 当e或E前面没有数字时,整个字符串不能表示数字,例如.e1、e1;
            // 2. 当e或E后面没有整数时,整个字符串不能表示数字,例如12e、12e+5.4
            numeric = scanInteger(s) && numeric;
        }
        return currentIndex == n && numeric;
    }

    /**
     * 整数的格式可以用[+|-]B表示, 其中B为无符号整数
     * @param s
     * @return
     */
    private boolean scanInteger(String s) {
        int n = s.length();
        if (currentIndex < n && (s.charAt(currentIndex) == '+' || s.charAt(currentIndex) == '-')) {
            currentIndex++;
        }
        return scanUsignedInteger(s);
    }

    private boolean scanUsignedInteger(String s) {
        int n = s.length();
        int beforeIndex = currentIndex;
        while (currentIndex < n && '0' <= s.charAt(currentIndex) && s.charAt(currentIndex) <= '9') {
            currentIndex++;
        }
        // 当str中存在若干0-9的数字时,返回true
        return currentIndex > beforeIndex;
    }
}


  1. 首先,将字符串的两端空格去除,并获取字符串的长度 n。如果去除空格后的字符串长度为0,直接返回 false。

  2. 初始化 currentIndex 为0,用于追踪当前扫描的位置。

  3. 调用 scanInteger(s) 方法判断字符串的整数部分。该方法会检查当前位置是否为正号或负号,如果是则将 currentIndex 增加1,并调用 scanUnsignedInteger(s) 方法判断无符号整数部分。

  4. 如果当前位置小于字符串长度且当前字符是小数点(‘.’),则将 currentIndex 增加1,并调用 scanUnsignedInteger(s) 方法判断小数部分。注意,小数部分可以没有整数部分,也可以没有小数点后的数字,因此使用逻辑或(||)将结果与 numeric 进行逻辑运算。

  5. 如果当前位置小于字符串长度且当前字符是指数符号(‘e’ 或 ‘E’),则将 currentIndex 增加1,并调用 scanInteger(s) 方法判断指数部分。指数部分必须包含整数,因此使用逻辑与(&&)将结果与 numeric 进行逻辑运算。

  6. 最后,判断 currentIndex 是否等于字符串长度,并且 numeric 是否为 true。如果满足条件,表示整个字符串可以解释为一个数值,返回 true;否则返回 false。

scanInteger() 方法用于判断整数部分:

获取字符串的长度 n。

如果当前位置小于字符串长度且当前字符是正号或负号(‘+’ 或 ‘-’),则将 currentIndex 增加1。

调用 scanUnsignedInteger(s) 方法判断无符号整数部分。

返回 scanUnsignedInteger(s) 的结果。

scanUnsignedInteger() 方法用于判断无符号整数部分:

获取字符串的长度 n。

初始化 beforeIndex 为 currentIndex 的值。

当 currentIndex 小于字符串长度且当前字符是数字字符(‘0’ 到 ‘9’ 之间的字符)时,将 currentIndex 增加1。

判断 currentIndex 是否大于 beforeIndex。如果大于,表示字符串中存在若干数字字符,返回 true;否则返回 false。

你可能感兴趣的:(剑指Offer,java,开发语言,面试)