问题描述
请你来实现一个 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 。
提示
- 0 <= s.length <= 200
- s 由英文字母(大写和小写)、数字(0-9)、’ ‘、’+‘、’-’ 和 ‘.’ 组成
思路分析
- 去除无用的前导空格:使用strip()函数去除字符串前后的空格。
- 检查符号位:判断第一个字符是否为正号或负号,若是则记录正负号,并将剩下的字符串赋给变量s。
- 读取数字字符并转换为整数:遍历字符串s的每个字符,判断是否为数字字符,如果是则将其转换为整数并累加到result中;如果遇到非数字字符,则跳出循环。
- 处理溢出情况:根据符号位判断最终结果的正负,并判断是否超出32位有符号整数范围[-2^31, 2^31-1],如果超出则返回范围边界值,否则返回result作为最终结果。
代码分析
- 读入字符串并丢弃无用的前导空格:使用
strip()
函数去除字符串前后的空格,将处理后的结果重新赋值给变量s
。这样可以消除输入字符串头部和尾部的空格。 - 检查符号:定义变量
sign
并初始化为 1(正号)。如果字符串s
非空,并且第一个字符是正号或负号,则根据符号字符决定sign
的值。如果第一个字符是负号,则将sign
赋值为 -1,并将剩下的字符串赋给变量s
。这样可以确定最终结果的正负。 - 读取数字字符并转换为整数:定义变量
result
并初始化为 0。使用循环遍历变量s
的每个字符c
,判断字符c
是否是数字字符。如果是,将其转换为整数并累加到result
上,通过乘以 10 来实现每次累加位数的增加。如果遇到非数字字符,跳出循环。这样可以逐个读取字符串中的数字字符,并计算出对应的整数值。 - 处理溢出情况:将
result
乘以符号位sign
,得到处理后的结果。然后进行溢出判断,如果结果小于下界 -2^31,则返回下界值 -2^31。如果结果大于上界 2^31-1,则返回上界值 2^31-1。否则,返回结果result
作为最终结果。
完整代码
class Solution(object): def myAtoi(self, s): """ :type s: str :rtype: int """ # 1. 读入字符串并丢弃无用的前导空格 s = s.strip() # 去除字符串首尾的空格 # 2. 检查符号 sign = 1 # 符号,默认为正号 if s and (s[0] == '+' or s[0] == '-'): # 判断第一个字符是否为正号或负号 if s[0] == '-': # 如果为负号 sign = -1 # 将符号设置为负号 s = s[1:] # 去除字符串中的符号部分,更新字符串 s # 3. 读取数字字符并转换为整数 result = 0 # 用于记录最终结果的变量 for c in s: # 遍历字符串中的每个字符 if not c.isdigit(): # 如果字符不是数字字符 break # 跳出循环 result = result * 10 + int(c) # 将字符转换为整数,并累加到结果中 # 4. 处理溢出情况 result = sign * result # 根据符号位确定最终结果的正负 if result < -2**31: # 判断是否小于下界 return -2**31 # 返回下界值 elif result > 2**31 - 1: # 判断是否大于上界 return 2**31 - 1 # 返回上界值 else: return result # 返回计算得到的结果作为最终结果
详细分析
s = s.strip()
: 去除字符串首尾的空格。strip() 方法用于移除字符串中指定字符,默认为空格。sign = 1
: 初始化符号变量为正号。符号用于表示最终整数是正数还是负数。if s and (s[0] == '+' or s[0] == '-'):
: 判断第一个字符是否为正号或负号。
- 判断条件中的
s
是一个非空字符串,因此判断s
是否为真意味着检查字符串是否为空。 - 如果第一个字符是
-
,将符号变量sign
设置为负号。 - 无论第一个字符是
+
还是-
,都需要去除字符串中的符号部分,所以将字符串s
更新为去除了第一个字符的子串。
result = 0
: 初始化用于记录最终结果的变量。默认情况下,结果为0。for c in s:
: 遍历字符串中的每个字符。
- 对于遍历到的每个字符
c
:
if not c.isdigit():
: 如果字符不是数字字符(即不是0-9的数字),则跳出循环。- 否则,将字符转换为整数,并将其累加到结果变量
result
中。通过将result
乘以10,可以将当前字符添加到result
的个位数位置。
result = sign * result
: 根据符号变量sign
确定最终结果的正负。如果sign
为1,则结果为正数;如果sign
为-1,则结果为负数。if result < -2**31:
: 判断是否小于下界-2**31
(即 -2147483648)。
- 如果结果小于下界,表示整数溢出,因此返回下界值
-2**31
。
elif result > 2**31 - 1:
: 判断是否大于上界2**31 - 1
(即 2147483647)。
- 如果结果大于上界,表示整数溢出,因此返回上界值
2**31 - 1
。
else:
: 如果结果没有溢出,返回计算得到的结果作为最终结果。
这个代码段用于将给定的字符串 s
转换为整数。它处理了输入字符串的空格、符号和非数字字符,以及整数溢出的情况,并返回相应的结果。
运行效果截图
调用示例
solution = Solution() s = "42" s1 = " -42" s2 = "4193 with words" print(solution.myAtoi(s)) print(solution.myAtoi(s1)) print(solution.myAtoi(s2))
运行结果
完结