题目来源
8. 字符串转换整数 (atoi) - 力扣(LeetCode)
题目描述
请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数。
函数 myAtoi(string s) 的算法如下:
- 空格:读入字符串并丢弃无用的前导空格(" ")
- 符号:检查下一个字符(假设还未到字符末尾)为 '-' 还是 '+'。如果两者都不存在,则假定结果为正。
- 转换:通过跳过前置零来读取该整数,直到遇到非数字字符或到达字符串的结尾。如果没有读取数字,则结果为0。
- 舍入:如果整数数超过 32 位有符号整数范围 [−231, 231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被舍入为 −231 ,大于 231 − 1 的整数应该被舍入为 231 − 1 。
返回整数作为最终结果。
示例 1
示例 2
示例 3
示例 4
示例 5
提示
- 0 <= s.length <= 200
- s 由英文字母(大写和小写)、数字(0-9)、' '、'+'、'-' 和 '.' 组成
题目解析
本题可以分为两部分逻辑:
- 读入最终结果数字串
- 判断最终结果数字串是否超出 int 范围
读入最终结果数字串逻辑如下:
- 首先,跳过前导空格
- 接着,读入最终结果的符号部分 sign,可能没有符号,此时默认为正数
- 最后,读入最终结果的数字部分 num,可能含有前导0,但是不影响结果
判断一个数字串是否超出 int 范围,我们可以从高位到低位,依次读取该数字串的每个字符 c,将计算结果记录进 res 中,res初始为0:
按上面公式,先计算进res的高位数字后续会不断 *10,抬高位序。
如果计算过程中,发现 res 超出了 int 范围(一步一步计算的过程,绝对不会超出 long 范围,因此 res 可以定义为 long 类型),则停止计算,返回对应 int 边界值。
更多细节逻辑,请看代码实现。
C源码实现
int myAtoi(char* s) {
int i = 0;
while (i < strlen(s) &= ' ') { // 跳过无用的前导空格
i++;
}
int sign = 1; // sign录入最终结果的符号部分, 1表示正, -1表示负, 默认为正
if (i < strlen(s) && (s[i] == '+' || s[i] == '-')) { // 如果有开头+或-号, 则更新sign信息
sign = s[i] == '-' ? -1 : 1;
i++;
}
char num[201] = {'\0'}; // num录入最终结果的数字部分
int num_size = 0;
for (; i < strlen(s); i++) {
if (s[i] >= '0' && s[i] <= '9') {
num[num_size++] = s[i];
} else {
break;
}
}
// 判断一个数值是否超过int范围
long res = 0;
for (int j = 0; j < num_size; j++) {
res = res * 10 + (num[j] - '0');
if (res * sign >= INT_MAX) {
return INT_MAX;
}
if (res * sign <= INT_MIN) {
return INT_MIN;
}
}
return (int)res * sign;
}
C++源码实现
class Solution {
public:
int myAtoi(string s) {
int i = 0;
while (i < s.length() &= ' ') { // 跳过无用的前导空格
i++;
}
int sign = 1; // sign录入最终结果的符号部分, 1表示正, -1表示负, 默认为正
if (i < s.length() &&
(s[i] == '+' || s[i] == '-')) { // 如果有开头+或-号, 则更新sign信息
sign = s[i] == '-' ? -1 : 1;
i++;
}
string num; // num录入最终结果的数字部分
for (; i < s.length(); i++) {
if (s[i] >= '0' && s[i] <= '9') {
num += s[i];
} else {
break;
}
}
// 判断一个数值是否超过int范围
long res = 0;
for (int j = 0; j < num.length(); j++) {
res = res * 10 + (num[j] - '0');
if (res * sign >= INT_MAX) {
return INT_MAX;
}
if (res * sign <= INT_MIN) {
return INT_MIN;
}
}
return (int) res * sign;
}
};
Java源码实现
class Solution {
public int myAtoi(String s) {
int i = 0;
while (i < s.length() && s.charAt(i) == ' ') { // 跳过无用的前导空格
i++;
}
int sign = 1; // sign录入最终结果的符号部分, 1表示正, -1表示负, 默认为正
if (i < s.length() && (s.charAt(i) == '+' || s.charAt(i) == '-')) { // 如果有开头+或-号, 则更新sign信息
sign = s.charAt(i) == '-' ? -1 : 1;
i++; // 跳过符号
}
StringBuilder num = new StringBuilder(); // num录入最终结果的数字部分
for (; i < s.length(); i++) {
char c = s.charAt(i);
if (c >= '0' '9') {
num.append(c);
} else {
break;
}
}
// 判断一个数值是否超过int范围
long res = 0;
for (int j = 0; j < num.length(); j++) {
res = res * 10 + (num.charAt(j) - '0');
if (res * sign >= Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
}
if (res * sign <= Integer.MIN_VALUE) {
return Integer.MIN_VALUE;
}
}
return (int) res * sign;
}
}
Python源码实现
class Solution(object):
def myAtoi(self, s):
"""
:type s: str
:rtype: int
"""
i = 0
while i < len(s) and s[i] == ' ': # 跳过无用的前导空格
i += 1
sign = 1 # sign录入最终结果的符号部分, 1表示正, -1表示负, 默认为正
if i < len(s) and (s[i] == '+' or s[i] == '-'): # 如果有开头+或-号, 则更新sign信息
sign = -1 if s[i] == '-' else 1
i += 1
num = "" # num录入最终结果的数字部分
while i < len(s):
if '9' >= s[i] >= '0':
num += s[i]
else:
break
i += 1
INT_MAX = pow(2, 31) - 1
INT_MIN = -pow(2, 31)
# 判断一个数值是否超过int范围
res = 0
for j in range(len(num)):
res = res * 10 + int(num[j])
if res * sign >= INT_MAX:
return INT_MAX
if res * sign <= INT_MIN:
return INT_MIN
return res * sign
JavaScript源码实现
/**
* @param {string} s
* @return {number}
*/
var myAtoi = function (s) {
let i = 0;
while (i < s.length &= " ") {
// 跳过无用的前导空格
i++;
}
let sign = 1; // sign录入最终结果的符号部分, 1表示正, -1表示负, 默认为正
if (i < s.length && (s[i] == "+" || s[i] == "-")) {
// 如果有开头+或-号, 则更新sign信息
sign = s[i] == "-" ? -1 : 1;
i++;
}
let num = ""; // num录入最终结果的数字部分
for (; i < s.length; i++) {
if (s[i] >= "0" && s[i] <= "9") {
num += s[i];
} else {
break;
}
}
const INT_MAX = Math.pow(2, 31) - 1;
const INT_MIN = -Math.pow(2, 31);
// 判断一个数值是否超过int范围
let res = 0;
for (let j = 0; j < num.length; j++) {
res = res * 10 + parseInt(num[j]);
if (res * sign >= INT_MAX) {
return INT_MAX;
}
if (res * sign <= INT_MIN) {
return INT_MIN;
}
}
return res * sign;
};