Skip to content
本页目录

67-把字符串转换成整数

题目描述

https://leetcode.cn/problems/ba-zi-fu-chuan-zhuan-huan-cheng-zheng-shu-lcof

写一个函数 StrToInt,实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。

首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。

当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。

该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。

注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。

在任何情况下,若函数不能进行有效的转换时,请返回 0。

说明:

假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为[−2^31, 2^31− 1]。如果数值超过这个范围,请返回 INT_MAX (2^31− 1) 或INT_MIN (−2^31) 。

示例1:

输入: "42"
输出: 42

示例2:

输入: "   -42"
输出: -42
解释: 第一个非空白字符为 '-', 它是一个负号。
    我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。

示例3:

输入: "4193 with words"
输出: 4193
解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。

示例4:

输入: "words and 987"
输出: 0
解释: 第一个非空字符是 'w', 但它不是数字或正、负号。
     因此无法执行有效的转换。

示例5:

输入: "-91283472332"
输出: -2147483648
解释: 数字 "-91283472332" 超过 32 位有符号整数范围。 
    因此返回 INT_MIN (−2^31) 。

思路分析

  1. 找出起始位和结束位置
  2. 找出符号位
  3. 从结束位置开始累加结果,中间判断结果是否大于最值

实现代码

csharp
public class Solution {
    public int StrToInt(string str) {
    	int start = 0;
    	int end = 0;
    	bool positive = true;
    	bool findSign = false;
    	int result = 0;
    	//处理空格
    	int index = 0;
    	while(str[index] == ' '){
    		index++;
    	}

        if(str[index] == '+' || str[index] == '-' || (str[index] > '0' && str[index] < '9')){
            start = index;
            if(str[index] == '+' || str[index] == '-'){
                index++;
                start++;
                positive = str[index] == '+';
            }
            while(index < str.Length){
                if(str[index] >= '0' && str[index] <= '9'){
                    end = index;
                }
                else{
                    break;
                }
                index++;
            }
            //Console.WriteLine("start{0},end{1}",start,end);

            int multi = 1;

            for(int i=end; i>=start; i--){
                int v = multi * (str[i] - '0');
                
                if(result > int.MaxValue - v){
                    if(positive){
                        return int.MaxValue;
                    }
                    else{
                        return int.MinValue;
                    }
                }

                result += v;
                multi *= 10;
            }
            if(!positive){
                result = -result;
            }
        }
    	return result;
    }
}

官方解法

两个地方优化了。

1个是判断最大值 int.MaxValue = 2147483647 去除最后一位取前面的位数,然后判断最后一位是否大于7即可 str[i] > '7' 这里处理很巧妙,判断 > '7' , 看似没有考虑 MIN, 但其实无论是 = '8' ,还是 >'8',返回的都是MIN。 即 2147483647 返回的就是这个数 2147483647, 如果是 -2147483648 则直接返回也不会出错,因为它就是 int.MinValue,如果再大的数,也是返回 int.MinValue

2 是不需要从 end 一直往前加了相乘,而是从前面把结果相乘10然后加到后面的新数字,这样还可以判断前缀是否是大于 int.MaxValue

  1. sign 用正负号表示,可以直接相乘返回即可

注意 比较的时候要用 char '7'


梳理一下:

从前往后依次处理,使用 i =0 表示开始处理位置,初始化 res = 0 作为最后结果

  1. 处理开始空格,直接跳过,如果跳过后,发现i到最后一位了,返回0
  2. 处理正负号 保存到 sign 变量中, sign 为 1 或者 -1,如果发现符号 i++
  3. 循环处理 for(int j=i 直到结束) 如果遇到非数字直接结束循环。 如果是数字 就加到 res 中去 注意要将之前的 res 乘以 10,因为如果 42, 先加了4,到加2的时候4要乘以10,后面一次类推 另外在增加一个判断最大值的越界问题, 使用 int.MaxValue / 10 作为boundary,左边的数 > boundary 或者等于 boundary 并且最后一位数 > '7' 说明越界了,根据符号返回对应的最大值,注意这里只需要判断7就可以了。
csharp
public class Solution{
	public int StrToInt(string str){
        if(str.Length == 0){
            return 0;
        }
		int res = 0;
		int boundry = int.MaxValue / 10;
		int i = 0;
		int sign = 1;
		int length = str.Length;
		while(str[i] == ' '){
			i++;
			if(i == length){
			 	return 0;
			}
		}
		if(str[i] == '-'){
			sign = -1;
		}
		if(str[i] == '-' || str[i] == '+'){
			i++;
		}

		for(int j=i; j<length; j++){
			if(str[j] < '0' || str[j] > '9'){
				break;
			}
			if(res > boundry || (res == boundry && str[j] > '7')){
				return sign == 1 ? int.MaxValue : int.MinValue;
			}
			res = res * 10 + (str[j] - '0');
		}
		return sign * res;
	}
}

复习:20220509

csharp
public class Solution {
    public int StrToInt(string str) {
        //去除开始的空格,如果一直到底就返回0
        //判断字符的符号
        //判断有效的字符,累加
        //判断是否越界 boundary = int.MaxValue / 10;
        if(str == ""){
            return 0;
        }
        int i=0; 
        int result = 0 ;
        int boundary = int.MaxValue / 10; //判断边界值
        int sign = 1; //符号
        while(str[i] == ' '){
            i++;
            if(i == str.Length){
                return 0;
            }
        }
        //判断符号
        if(str[i] == '-'){
            sign = -1;
        }
        if(str[i] == '-' || str[i] == '+'){
            i++;
        }
        //判断数字
        while(i < str.Length){
            //不合法停止判断
            if(str[i] < '0' || str[i] > '9'){
                break;
            }
            //判断是否越界
            if(result > boundary || result == boundary && str[i] > '7'){
                return sign == 1 ? int.MaxValue : int.MinValue;
            }

            result = result * 10 + str[i] - '0';
            i++;
        }

        return sign * result;

    }
}

Released under the MIT License.