一道看起来很简单的题,最后居然写成了代码屎山?【字符串转换整数 (atoi)】【力扣训练】【蓝桥杯训练】


前言

这几天在力扣练题的时候,遇到了这样一道题,将一个字符串中的整数提取出来,看完题目我觉得是一道非常简单的题目,可是一提交,就会遇到各种特例,然后错误,于是就在代码上加参数,加条件语句,最后代码就写成了屎山。现在来复盘一下这道题。(特例见文末总结)

题目(中等)

请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。

函数 myAtoi(string s) 的算法如下:

读入字符串并丢弃无用的前导空格
检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
将前面步骤读入的这些数字转换为整数(即,“123” -> 123, “0032” -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
如果整数数超过 32 位有符号整数范围 [−231,231−1 ] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于−231 的整数应该被固定为−231,大于 231−1 的整数应该被固定为 231−1 。
返回整数作为最终结果。

注意
本题中的空白字符只包括空格字符 ’ ’ 。
除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。

示例 1
输入:s = “42”
输出:42
解释:加粗的字符串为已经读入的字符,插入符号是当前读取的字符。
第 1 步:“42”(当前没有读入字符,因为没有前导空格)
^
第 2 步:“42”(当前没有读入字符,因为这里不存在 ‘-’ 或者 ‘+’)
^
第 3 步:“42”(读入 “42”)
^
解析得到整数 42 。
由于 “42” 在范围 [−231,231−1 ] 内,最终结果为 42 。

示例 2:
输入:s = " -42"
输出:-42
解释:
第 1 步:" -42"(读入前导空格,但忽视掉)
^
第 2 步:" -42"(读入 ‘-’ 字符,所以结果应该是负数)
^
第 3 步:" -42"(读入 “42”)
^
解析得到整数 -42 。
由于 “-42” 在范围 [−231,231−1 ] 内,最终结果为 -42 。

示例 3:
输入:s = “4193 with words”
输出:4193
解释:
第 1 步:“4193 with words”(当前没有读入字符,因为没有前导空格)
^
第 2 步:“4193 with words”(当前没有读入字符,因为这里不存在 ‘-’ 或者 ‘+’)
^
第 3 步:“4193 with words”(读入 “4193”;由于下一个字符不是一个数字,所以读入停止)
^
解析得到整数 4193 。
由于 “4193” 在范围 [−231,231−1 ] 内,最终结果为 4193 。

示例 4:
输入:s = “words and 987”
输出:0
解释:
第 1 步:“words and 987”(当前没有读入字符,因为没有前导空格)
^
第 2 步:“words and 987”(当前没有读入字符,因为这里不存在 ‘-’ 或者 ‘+’)
^
第 3 步:“words and 987”(由于当前字符 ‘w’ 不是一个数字,所以读入停止)
^
解析得到整数 0 ,因为没有读入任何数字。
由于 0 在范围 [−231,231−1 ] 内,最终结果为 0 。

示例 5:
输入:s = “-91283472332”
输出:-2147483648
解释:
第 1 步:"-91283472332"(当前没有读入字符,因为没有前导空格)
^
第 2 步:"-91283472332"(读入 ‘-’ 字符,所以结果应该是负数)
^
第 3 步:"-91283472332"(读入 “91283472332”)
^
解析得到整数 -91283472332 。
由于 -91283472332 小于范围 [−231,231−1 ] 的下界,最终结果被截断为 −231 = -2147483648 。

提示:

0 <= s.length <= 200
s 由英文字母(大写和小写)、数字(0-9)、’ ‘、’+’、’-’ 和 ‘.’ 组成

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/string-to-integer-atoi


分析

题目意思,显而易见,就是给出一段字符串,这个字符串中如果能提取出整数,那么第一个数字前面一定是以“空格+正负号”;“仅空格”;“什么也没有”,这三种形式开头。提取出现的第一个整数。我的做法是:

  1. 遍历原字符串s,判断到空格则继续遍历下一个,若遍历到不是空格:若这个字符不属于数字和正负号就直接返回0;若字符属于数字或正负号,则记录该下标 j ,并结束循环。
  2. 从下标 j 开始重新遍历字符串s,将其中的首字符,以及数字提取出来放到数组 num 中,遇到不是数字,或正负号就结束循环。
  3. 判断 num 的长度,若为 1 则判断是否为正负号,若为则直接返回 0。
  4. 将数组 num 转为字符串,再转为整数,判断它的取值范围[−231,231−1 ] 返回即可。

代码

代码如下:

class Solution:
    def myAtoi(self, s: str) -> int:
        nums = ['1','2','3','4','5','6','7','8','9','0'] #数字
        fu = ['-','+'] #正负号
        num = [] #用于存放整数
        n = len(s) #字符串长度
        if n == 0: #字符串长度为 0 直接返回 0 
            return 0
        for i in range(n): #从头开始遍历字符串s
            if s[i] == ' ' and i != n - 1: #是空格,并且不是最后一个字符,跳过本次循环,进行下一次
                continue
            elif s[i] == ' ' and i == n-1: #最后一个字符仍为空格,返回 0
                return 0
            else: #中间
                if s[i] in fu or s[i] in nums: #若为正负号,或者数字记录当前下标,并结束循环
                    j = i
                    break
                else:
                    return 0
 
        for i in range(j,n): #从刚才记录的下标开始遍历
            if i == j:  #如果是第一个字符,判断是否是正负号,或者数字,是便添加到 num 中。
                if s[i] not in nums and s[i] not in fu:
                    return 0
                else:
                    num.append(s[i])
            else: #不是第一个字符
                if s[i] not in nums: #不属于数字,结束循环
                    break
                else: #属于数字,将它添加到 num 
                    num.append(s[i]) 
        if len(num) == 1: #判断 num 的长度是否为1
            if num[0] == '-' or num[0] == '+': #如果该字符为正负号,则直接返回 0 
                return 0
        st = ''.join(num) #数组转为字符串
        Max = 2 **31 - 1 #上限
        Min = (-2) ** 31 #下限
        ans = max(Min,(min(int(st),Max))) #判断大小
        return ans


总结

最后当然是成功通过:
在这里插入图片描述
这里,给几个我提交出错的几个例子:
s = “+”
s = “00000-42a1234”
s = " "
s =“±12”
s = “3.14159”
s =""


码字不易,点个赞再走叭。
一起进步!

猜你喜欢

转载自blog.csdn.net/youngwyj/article/details/122662959