题目:
字符串转换整数 (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