(python version) 剑指offer 20.表示数值的字符串

题目描述

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
例如,字符串"+100"、"5e2"、"-123"、"3.1416"、"0123"都表示数值,
但"12e"、"1a3.14"、"1.2.3"、"+-5"、"-1E-16"及"12e+5.4"都不是。

解题思路

  • 首先以 . 作为分割字符串,以此为主体,依照分割的个数判断数值形式
1. 分割个数若为 1

最主要的逻辑判断在此(递归主要使用此处):
(1) 判断正负符号次数
(2) 判断指数型态 e|E:不为首、若不为首前面不为正负号、判断指数的底数为整数
(3) 其馀除了正负号外,若不为数字的,则直接返回 False
(4) 最后判断 num of sign 超过2个(含)或是没有该字串没有任何数字则为 False; 其馀情况皆为 True

2. 分割个数若为 2(依序讨论)

小数点前为 A 、小数点后为 B

  • 限制条件:
    (1) A 存在 e|E :False
    (2) B为小数点的部分,若出现正负符号则返回 False; 若出现首位为 e |E的情形,则以 ‘1’+B (e.g. B = ‘e0’; ‘1’+B = ‘1e0’) 带入递归返回结果
  • 依序讨论:
    (1) A空B有:返回 isNumber(B) => 回到分割数为1 的逻辑判断
    (2) A有B空:返回 isNumber(A) => 回到分割数为1 的逻辑判断
    (3) A有B有:加上条件,若A为单一正or负号,返回 isNumber(B); 其馀为 isNumber(A) and isNumber(B) 成立时,返回 True,其馀返回 False
    (4) 其他:返回 False
3. 分割个数>2

返回False


小结

这次使用条件式判断,排除那些不成立(不过之后可以考虑列举成立的情况,其馀皆为不成立)。虽然是 Medium 的难度,但仍花了较多的时间处理众多 Special Case,蒐集如下。

  • Special Case: ‘0’, ‘1 3’, ‘1 ‘, ‘6+1’, ‘.-4’, ‘+e5’,’-01’, ‘46.e3’, ‘6e.5’, ‘000e313e013’, ‘0130e+6’, ‘+E3’, ‘te1’, ‘2e0’

Python 代码

import re
class Solution:
    def isNumber(self, s: str) -> bool:
        # 符号的次数,超过一次即返回False
        num_of_sign = 0
        num_of_word = 0

        # special case: 空字串
        if not s:
            return False
        s = s.strip()

        # special case: 出现两个以上的e
        if len(s.split('e')) >2:
            return False

        # 一个空白字符 判断是否包含空白字符
        if len(s) != len(s.replace(' ', '')) :
            return False

        s = s.replace(' ', '.')
        s_list = s.split('.')

        if len(s_list) == 1 and len(s_list[0]) !=0:
            single_s = s_list[0]
            # 统计正负号次数
            for i in range(len(single_s)):
                if single_s[i] == '+' or single_s[i] == '-':
                    num_of_sign+=1
                    # 正负号不在第一位
                    if i >0:
                        return False

                if single_s[i] == 'e' or single_s[i] == 'E':
                    # e位于首位
                    if i == 0:
                        return False
                    # 前一位如果是正负号
                    elif i < len(single_s)-1:
                        if single_s[i-1] == '+' or single_s[i-1] == '-':
                            return False
                        else:
                        # 判断是否为整数的递归:若后面为小数, 则会因为有两个'.', 而返回False
                            return Solution().isNumber(single_s[i+1:]+'.')
                    else:
                        return False
                
                # 不包含数字,除了正负号以及 e|E 以外的字都应该是数字,若不为数字则返回 False
                elif not bool(re.search(r'\d', single_s[i])):
                    if i == 0 and single_s[i] == '+' or single_s[i] == '-':
                        pass 
                    else:
                        return False
                else:
                    pass

            # 若上述皆符合但是有两个以上的正负号 或是 没有任何数字
            if num_of_sign >1 or not any(chr.isdigit() for chr in single_s):
                return False 
            else:
                return True
        
        elif len(s_list) == 2:
            A = s_list[0]
            B = s_list[1]
            # Special case: 右半边的情况出现正负号,返回False; 右半边如果第一位为e,则以 1e. 进行递归 (#46.e3)
            if len(B)>0:
                if B[0] == '+' or B[0] == '-':
                    return False
                if (B[0] == 'e' or B[0] == 'E') and Solution().isNumber(A):
                    return Solution().isNumber('1'+B)
            
            # 如果左边出现e,返回False
            i = 0
            for i in range(len(A)):
                if A[i] == 'e' or A[i] == 'E':
                    return False

            # 前有后有
            if A and B:
                # 左边只出现单一符号
                if A == '+' or A == '-':
                    return Solution().isNumber(B)
                if Solution().isNumber(A) and Solution().isNumber(B):
                    return True
                else:
                    return False

            # 前有后空
            elif A and not B:
                return Solution().isNumber(A)
            # 前空后有
            elif not A and B:
                return Solution().isNumber(B)
            # 前空后空
            else:
            	return False
        
        else:
            return False

你可能感兴趣的:((python version) 剑指offer 20.表示数值的字符串)