问题描述:
实现一个将字符串转换为整数的函数时,需要考虑各种边界情况和细节,例如空格的处理、符号的判断、数字的读取以及整数溢出的处理等。以下是详细的解题过程以及代码实现。
问题分析
-
空格处理:需要丢弃字符串开头的空格字符。
-
符号判断:检查字符串的第一个有效字符是否为正或负号。
-
数字读取:读取连续的数字字符,直到遇到非数字字符或字符串结束。
-
整数溢出处理:确保读取的整数不超过32位有符号整数的范围。
解题思路
-
初始化:初始化一个索引用于遍历字符串,以及标志符号的变量。
-
跳过前导空格:遍历字符串直到第一个非空格字符。
-
判断符号:检查第一个非空格字符是否为正或负号,并设置相应的符号。
-
读取数字字符:遍历字符,将连续的数字字符转换为整数,同时检查是否溢出。
-
处理溢出:在每一步累加时,检查是否超过32位整数的最大或最小值。
class Solution {public int myAtoi(String s) {int index = 0; // 初始化索引,用于遍历字符串int sign = 1; // 初始化符号为正int result = 0; // 初始化结果为0int n = s.length(); // 获取字符串长度// 跳过字符串开头的所有空格字符while (index < n && s.charAt(index) == ' ') {index++;}// 检查当前字符是否为正号或负号,以确定整数的符号if (index < n && (s.charAt(index) == '+' || s.charAt(index) == '-')) {sign = (s.charAt(index) == '+') ? 1 : -1; // 根据符号更新sign变量index++; // 移动索引到下一个字符}// 遍历字符串,读取连续的数字字符while (index < n && Character.isDigit(s.charAt(index))) {int digit = s.charAt(index) - '0'; // 将字符转换为对应的数字// 检查是否溢出:如果当前结果大于 (Integer.MAX_VALUE - digit)/10,则下一次乘10加digit会溢出if (result > (Integer.MAX_VALUE - digit) / 10) {// 如果溢出,根据符号返回最大或最小值return (sign == 1) ? Integer.MAX_VALUE : Integer.MIN_VALUE;}// 将当前数字加入结果result = result * 10 + digit;index++; // 移动到下一个字符}// 返回带有符号的结果return sign * result;}
}
时间复杂度
该算法的时间复杂度为 O(n),其中 n 是字符串的长度。这是因为算法中各个步骤的复杂度如下:
-
跳过前导空格:最坏情况下,可能需要遍历整个字符串(如果字符串全是空格),时间复杂度为 O(n)。
-
处理符号:仅检查一个字符,时间复杂度为 O(1)。
-
读取数字字符:最坏情况下,可能需要遍历整个字符串(如果字符串全是数字),时间复杂度为 O(n)。
空间复杂度
该算法的空间复杂度为 O(1),因为只使用了少量的额外变量(如 index
、sign
、result
等),所使用的额外空间不随输入字符串的长度变化而变化。