剣はオファー67を指します。文字列を整数に変換します(状況は複雑です。慎重に検討してください)

2021年2月12日金曜日、天気は良いです[過去を嘆いたり、現在を無駄にしたり、未来を恐れたりしないでください]


1.はじめに

ソードフィンガーオファー67.文字列を整数に変換する

ここに画像の説明を挿入
ここに画像の説明を挿入

2.状況は複雑です。慎重に検討してください

2.1 1本のブラシ(2021.2.12)

class Solution {
    
    
    public:
        int strToInt(string str) {
    
    
        int res = 0, bndry = INT_MAX / 10;
        int i = 0, sign = 1, length = str.size();
        if(length == 0) return 0;

        // 删除开头的空格
        while(str.at(i) == ' ')
            if(++i == length) return 0;
        // 判断是否是负数
        if(str.at(i) == '-') sign = -1;
        // 跳过符号位
        if(str.at(i) == '-' || str.at(i) == '+') ++i;
        // 计算数值的大小
        for(int j = i; j < length; j++) {
    
    
            // 不是数字直接退出
            if(str.at(j) < '0' || str.at(j) > '9') break;
            // 巧妙判断数字是否越界
            if(res > bndry || res == bndry && str.at(j) > '7')
                return sign == 1 ? INT_MAX : INT_MIN;
            res = res * 10 + (str.at(j) - '0');
        }
        return sign * res;
    }
};

2.2 2番目のブラシ(2021.3.15)

上司のコードを最初の筆で直接再現し、2番目の筆で書き直したところ、主に数が範囲外かどうかを判断するために別の感覚を見つけました。上司の書き方は非常に巧妙ですが、私の方法は単純明快で、実際の面接で思いつくのは簡単です。

class Solution {
    
    
public:
    int myAtoi(string s) {
    
    
        const int n = s.size();
        int i = 0, num = 0;
        bool sign = true;

        // 删除开头的空格
        while(i<n && s[i]==' ') ++i;
        if(i>=n) return 0;
        // 判断是否是负数
        if(s[i]=='-') sign = false;
        // 跳过符号位
        if(s[i]=='-' || s[i]=='+') ++i;
        
        // 计算数值的大小
        int tmp = 0;
        while(i<n && isdigit(s[i])){
    
    
            tmp = s[i]-'0';
            // 判断数字是否越界
            if(num<=(INT_MAX-tmp)/10) num = 10*num + tmp;
            else break;   
            ++i; 
        }
        // 这里需要注意的是 if 的条件,不能用 if(num<=(INT_MAX-tmp)/10) 来判断
        // 原因是 num 的值本身可能略小于 INT_MAX,就会出现 num>(INT_MAX-tmp)/10,就没法返回 num 了
        if(i<n && isdigit(s[i])) return sign?INT_MAX:INT_MIN;
        else return sign?num:-num;    
    }
};

2.3無効な入力と整数オーバーフローを考慮する

『ソードフィンガーオファー第2版』では、無効な入力(数字を読まないと入力が無効とみなされる)と整数オーバーフローの状況を考慮していますが、現時点ではもう少し面倒なので2つ使う必要があります反映するグローバルフラグ変数であり、コードもわずかに変更されています。

入力が無効かどうかは、符号ビットを判断することで確認できます。整数オーバーフローは、INT_MINオーバーフローとINT_MAXオーバーフローに分けられます。オーバーフローするかどうかを判断するときは、INT_MAX(2147483647)が使用されるため、INT_MIN(-2147483648)の入力はまた、オーバーフローと見なされます。この状況には特別な考慮が必要です。

class Solution {
    
    
public:
	bool isVaild = true;
	bool isOverflow = false;

public:
	int myAtoi(string s) {
    
    
		// 默认输入是有效的,且没有溢出
		isVaild = true;
		isOverflow = false;

		const int n = s.size();
		int i = 0, num = 0;
		bool sign = true;

		// 删除开头的空格
		while (i < n && s[i] == ' ') ++i;
		// 判断是否是负数
		if (i < n && s[i] == '-') sign = false;
		// 跳过符号位
		if (i < n && (s[i] == '-' || s[i] == '+')) ++i;

		// 判断输入是否有效(如果没有读到数字,则认为输入是无效的)
		if (i >= n || !isdigit(s[i])) {
    
    
			isVaild = false;
			return 0;
		}

		// 计算数值的大小
		int tmp = 0;
		while (i < n && isdigit(s[i])) {
    
    
			tmp = s[i] - '0';
			// 判断数字是否越界(因为使用的是 INT_MAX(2147483647) 来判断是否越界,所以 -2147483648 会被认为越界了)
			if (num <= (INT_MAX - tmp) / 10) num = 10 * num + tmp;
			else break;
			++i;
		}
		// 这里需要注意 if 的条件,不能用 if(num<=(INT_MAX-tmp)/10) 来判断
		// 原因是 num 的值本身可能略小于 INT_MAX,就会出现 num>(INT_MAX-tmp)/10,就没法返回 num 了
		if (i < n && isdigit(s[i])) {
    
    
			// 如果输入不是最小的整数 INT_MIN(-2147483648),说明真的越界了
			if (!(sign == false && num == INT_MAX / 10 && tmp == 8)) isOverflow = true;
			return sign ? INT_MAX : INT_MIN;
		}
		else return sign ? num : -num;
	}
};


参照

「ソードフィンガーオファー第2版」

https://leetcode-cn.com/problems/ba-zi-fu-chuan-zhuan-huan-cheng-zheng-shu-lcof/solution/mian-shi-ti-67-ba-zi-fu-chuan- zhuan-huan-cheng-z-4 /

おすすめ

転載: blog.csdn.net/m0_37433111/article/details/113797685