python: LeetCode初级算法——字符串转成整数atoi

初级算法 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台icon-default.png?t=N176https://leetcode.cn/leetbook/read/top-interview-questions-easy/xnoilh/

题目:

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

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

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

注意:

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


以上是题目内容,原题目中所包含的示例不再列出。

这道题似乎很简单,但如果轻易开始,就会不断报错,并根据错误不断填补代码。原因在于:题目太长,简单扫两眼大概知道步骤和做法,没有认真读题,草率开始,却忽略很多细节。与其这样回头debug,不如按照步骤一步一步来做。

关键在于认真读题,题目中将每一步都标注清楚,所以按照步骤来实现即可。

同时,为了避免某一步骤出现问题,影响结果,完成每一个步骤之后都应该输入不同、符合、不符合要求的数字进行测试,出现问题后及时改正,减少debug时间。


class Solution:
    def myAtoi(self, s: str) -> int:
        

读到这里,可以发现,输入的是一串字符串,输出的是整数型。再读题的第一步:

""" 读入字符串并丢弃无用的前导空格 """

注意这里说的是“丢弃前导空格”,意味着这一步骤内,我只需要删除字符串前端的空格即可。

for item in range(len(s)):
    if s[item] != " ":
        s = s[item:]
        break
 

用切片遍历完前面的空格之后,直接将后面的内容全部保留。(如果没有前导空格则直接输出整个字符串)。

但是要考虑到多种情况:如果字符串里只有空格怎么办?

那么我们只需要判断切片后得到的字符串s是否为空即可,因此加上下列代码:

if s == "":
    return 0

之后来做第二步:

"""检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。
 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正"""

这一步只确定其正负号。我们可以将该符号提出来,作为signal单独储存,如果是“-”,则将signal赋值为-1,如果是“+”,则赋值为“1”,如果没有符号,也默认signal为1。同时,将原字符串内部的“-”或“+”切掉,只保留后面的部分。

signal = 1
if s[0] == "-":
    signal = -1
    s = s[1:]
elif s[0] == "+":
    signal = 1
    s = s[1:]

if s == "":
    return 0
                    

这里依然需要确认下去掉正负号的字符串是否为空。

运行这里,需要在控制台上输入相对应的字符串进行测试,减少debug时间。

这步测试无误后,进行下一步:

"""读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。"""

这里依然可以用切片来解决,那么如何判断字符串中的元素是否为数字呢?这里可以用ord()函数,将字符串转化为ascii数即可,只需要判断数字的范围。

代码如下:

for item in range(len(s)):
    if ord(s[item]) < ord("0") or ord(s[item]) > ord("9"):
        s = s[0:item]
        break
        
if s == "":
    return 0

注意,一旦出现不属于数字的元素,立刻跳出循环,否则就会不断切片。

在这步循环结束后也需要判断一下字符串是否为空。(毕竟可能只有字母或者是数字在字母后面)

下一步:

"""将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。
如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。"""

如何将字符串转化为整数型且不用int()函数?

还是可以用ASCII,虽然他们的编码是48~57,但是他们的差,不就是整数型的数字吗?

不过使用ord()计算后的每一位都是0~9的数字,要想输出为整数型,还需要将每一个数字“归位”,其实也很简单,我创建一个为0的整数型变量,遍历一个字符串元素,转换成整数型元素,让整数型变量加上整数型元素,再×10,最后结果再÷10,同时用前面留下的signal判断正负。

代码如下:

num = 0
for i in s:
    k = ord(i) - ord("0")
    num += k
    num = num * 10
num = signal * num // 10        

下一步:

"""
如果整数数超过 32 位有符号整数范围 [−231,  231 − 1] ,
需要截断这个整数,使其保持在这个范围内。
具体来说,小于 −231 的整数应该被固定为 −231 ,
大于 231 − 1 的整数应该被固定为 231 − 1 。
"""

这个比较简单,直接上代码:

if num > 2**31 - 1:
    return 2**31 - 1
elif num < -2**31:
    return -2**31
else:
    return num

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值