【求知=>算法】字符串转换整数 (atoi)

92 阅读5分钟

【求知=>算法】字符串转换整数 (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)’ ‘’+’’-‘’.’ 组成

解题思路


本题考查的逻辑问题比较繁琐,首先需要去除字符串前后的空格,判断是否为空,如果为空就返回往下走,判断符号,最后读取数字。

  1. 双循环方式

  • 定义字符串s, 并赋值为s = “42”;
  • 去除前后空格并定义为str = s.strip();
  • 定义bool类型sign = True;
  • 定义r,并赋值为r = 0;
  • 第一层循环判断符号和为空的情况;
  • 第二层循环判断是否是整型,r = r*10,然后r = r + i;
  • 判断是否是整型,在判断值是否大于2**31 - 1,如果大于返回r;
  • 如果不大于2**31 - 1,判断值r大于2 ** 31,就返回0 - (2**31),否则返回0 - r;
# s = "42"
# s = "  -42"
# s = "4193 with words"
s = "words and 987"
str = s.strip()
sign = True
r = 0

for i in range(len(str)):
    if str[i] == "-":
        sign = False
        str = str[i+1:]
        break
    if str[i] == "+":
        str = str[i + 1:]
        break

    if s[i] != " ":
        s = s[i:]
        break

for i in str:
    if i.isdigit():
        r *= 10
        r += int(i)
    else:
        break

if sign:
    if r > 2**31 - 1:
        return 2 ** 31 - 1
    return r
else:
    if r > 2 ** 31:
        return 0 - (2**31)
    return 0 - r
  1. 通过正则表达式的方式

  • 定义字符串s, 并赋值为s = “42”;
  • 去除前后空格并定义为str = s.strip();
  • 通过正则表达式检查正负号有无以及是否为数字;
  • 定义字符串news,并赋值为news = re.match(pattern, s);
  • 如果过滤有正负号不是数字就返回0;
  • 否则,先定义nums,并赋值为nums = int(news.group());
  • 如果nums小于(n := -2 ** 31)否则nums大于(n := 2 ** 31 - 1),返回n,否则返回nums;
s = "42"
# s = "  -42"
# s = "4193 with words"
# s = "words and 987"
s = s.strip(" ")  # 去除前端空格
pattern = r'[+|-]?[0-9]+'  # 正则表达,检查正负号有无以及是否为数字
news = re.match(pattern, s)
if not news:
    return 0
else:
    nums = int(news.group())
    if nums < (n := -2 ** 31) or nums > (n := 2 ** 31 - 1):
        return n
    else:
        return nums
  1. 双指针方式

  • 定义字符串s, 并赋值为s = “42”;
  • 定义start和end,并赋值为start = -1end = 0;
  • 第一层循环去除空格,和判断是否是整型,返回start = i,否则返回0;
  • 如果start == -1,返回0,将start值赋值为end;
  • 第二层循环判断是否是整型,将end += 1,否则往下走;
  • 定义为为result,并赋值为int(s[start:end + 1]);
  • 如果result大于2 ** 31 - 1返回2 ** 31 - 1,如果result小于-2 ** 31返回-2 ** 31,否则返回result;
s = "42"
# s = "  -42"
# s = "4193 with words"
# s = "words and 987"
start = -1
end = 0
for i in range(len(s)):
    if s[i] == ' ':
        continue
    elif s[i] == '+' or s[i] == '-':
        if i < len(s) - 1 and s[i + 1].isdigit():
            start = i
            break
        else:
            return 0
    elif s[i].isdigit():
        start = i
        break
    else:
        return 0
if start == -1:
    return 0
end = start
for i in range(start + 1, len(s)):
    if s[i].isdigit():
        end += 1
    else:
        break
result = int(s[start:end + 1])
if result > 2 ** 31 - 1:
    return 2 ** 31 - 1
elif result < -2 ** 31:
    return -2 ** 31
else:
    return result

知识扩展


isdigit()方法的使用

博客来源:雨夜的博客