leetcode刷题:第8题(数论)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chekongfu/article/details/82917876

一、题目描述

Implement atoi which converts a string to an integer.
The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.
The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.
If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
If no valid conversion could be performed, a zero value is returned.
Note:
• Only the space character ’ ’ is considered as whitespace character.
• Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. If the numerical value is out of the range of representable values, INT_MAX (231 − 1) or INT_MIN (−231) is returned.
Example 1:

Input: “42”
Output: 42

Example 2:

Input: " -42"
Output: -42
Explanation: The first non-whitespace character is ‘-’, which is the minus sign. Then take as many numerical digits as possible, which gets 42.

Example 3:

Input: “4193 with words”
**Output: **4193
Explanation: Conversion stops at digit ‘3’ as the next character is not a numerical digit.

Example 4:

Input: “words and 987”
Output: 0
Explanation: The first non-whitespace character is ‘w’, which is not a numerical
digit or a +/- sign. Therefore no valid conversion could be performed.

Example 5:

Input: “-91283472332”
Output: -2147483648
Explanation: The number “-91283472332” is out of the range of a 32-bit signed integer. Thefore INT_MIN (−231) is returned.

二、解题思路

本题是从输入的一串字符中按规则找出一个整数型的数字:规则如下:

  1. 数字第一个字符规则:当第一个非空字符为0-9、+、-表示数字组合开始,如果是‘ ’则不算数字组合开始,继续找第一个字符,如果是其他字符,数字组合失败,返回结果0。
  2. 数字组合开始后,当遇到的字符str[i]为0-9,按照result*10+str[i]的公式组合下去,组合之前要判断result组合之后的结果是否会溢出。当遇到非数字的字符,组合终止。
  3. 关于判断溢出,int类型的数字最大值INT_MAX是0x7fffffff(231-1),它的十进制是2147483647;最小值是0x8fffffff(-231),它的十进制是-2147483648.(写到这个地方,笔者一直有个坏习惯,喜欢刨根问底,这样就很耽误正事,这里带出一个问题“什么是溢出?”,这个问题下面单讲。)在每次组合新的数字str[i]前,拿之前组合得到的数字result和214748364相比较,如果result>214748364,那么组合后结果肯定溢出,如果result=214748364,那要看str[i]=9肯定溢出,str[i]=8当result为负不溢出;result为正肯定溢出。
    什么是溢出?
    在搞清楚此问题之前,要搞清楚什么是补码表示法?补码表示法最高位是符号位,0表示证书,1表示复数,正数用原码表示,负数用反码加一表示,因为不偏离主题过远,就不面面俱到的写。再此举个例子,比如现在个数字类型用4位表示,7在计算机中存储为0111,-6为1010,计算过程是6为110,取反后为001,加1为010,加上符号位就是1010。
    溢出简单点说就是给定数字类型位数表示不了目标数。比如int,它的位数是32,表示的最大数值是0x7fffffff(2147483647),也就是说2147483648用int类型表示不了。现在有个小问题,temp=2147483647,temp=temp+1之后temp是多少?temp用补码表示为0x7fffffff也就是0111 1111 1111 1111 1111 1111 1111 1111,加一之后为1000 0000 0000 0000 0000 0000 000 000,但是此时的值为最大的复数-2147483648,这个可以用代码验证
	int temp = INT_MAX ;
	temp += 1;
	cout<<temp<<endl;

在这里插入图片描述
再举个例子:temp = INT_MAX; temp = temp + temp; cout<<temp<<endl;结果会是多少?
temp:0111 1111 1111 1111 1111 1111 1111 1111,temp+temp为1111 1111 1111 1111 1111 1111 1111 1110;我们很容易知道此补数表示的是-2。那temp=INT_MIN;temp=temp+temp结果又是多少呢?temp:1000 0000 0000 0000 0000 0000 0000 0000
temp+temp:1 0000 0000 0000 0000 0000 0000 0000 0000,笔者认为是一个非常好的例子,因为他真正贴合“溢出”的含义,因为int只有32位,计算的结果是33位,那样只能舍去溢出的最高位1,所以结果是0。

笔者根据思路分别用C++、java、python三种语言写出了此题答案。

C++版答案

#include<iostream>
using namespace std;

class Solution {
	public:
		int myAtoi(string str) {
			
			//INT_MAX:2147483647
			//INT_MIN:-2147483648
			int max = 214748364 ;//用于处理找到的数字过大越界问题 
			int flag = 1;		//记录结果正负值 
			int result = 0;
			int strlength = str.size();
			bool isBegin = false; //找到第一个不是' '的字符,就认为是已经开始找组数字了 

			for(int i=0; i<strlength; i++) {
				if( !isBegin ) { //数字未被赋值 
					if( str[i] == ' ') {
						continue;
					} else if (str[i] == '-') {
						flag = -1;
						isBegin = true; 
					} else if (str[i] == '+' ) {
						isBegin = true;
					}else if( str[i] < 58 and str[i] > 47 )	{
						result =  result * 10 + ( str[i] - 48 );
						isBegin = true;
					} else {//当结果为0,初次遇到非数字的字符,认为结果就是0并返回 
						isBegin = true;
						break; 
					}
				} else {
					if ( str[i] < 58 && str[i] > 47 ) {
						if( result > max ) {
							return flag == 1?INT_MAX:INT_MIN;
						} else if ( result == max ) {
							if (flag == 1 && (str[i] -48) >= 7 ) {
								return INT_MAX;
							} else if ( flag == -1 && (str[i] -48) >= 8 ){
								return INT_MIN; 
							} 
						}
						result =  result * 10 + ( str[i] - 48 );
					} else {
						break;
					} 
				}
			}
			
			//result没有越界 
			result = flag * result;
 
			if( result > INT_MAX ) result = INT_MAX;
			if( result < INT_MIN ) result = INT_MIN;
			return result;  
		}
};

int main() {
	Solution s ;
	cout<<"s.myAtoi(\"42\")的结果是:"<<s.myAtoi("42")<<endl;
	cout<<"s.myAtoi(\"-42\")的结果是:"<<s.myAtoi("-42")<<endl;
	cout<<"s.myAtoi(\"4193 with words\")的结果是:"<<s.myAtoi("4193 with words")<<endl;
	cout<<"s.myAtoi(\"words and 987\")的结果是:"<<s.myAtoi("words and 987")<<endl;
	cout<<"s.myAtoi(\"-91283472332\")的结果是:"<<s.myAtoi("-91283472332")<<endl;
	cout<<"s.myAtoi(\"  0000000000012345678\")的结果是:"<<s.myAtoi("  0000000000012345678")<<endl;
	cout<<"s.myAtoi(\"+-2\")的结果是:"<<s.myAtoi("+-2")<<endl;
	cout<<"s.myAtoi(\"-000000000000001\")的结果是:"<<s.myAtoi("-000000000000001")<<endl;
	cout<<"s.myAtoi(\"010\")的结果是:"<<s.myAtoi("010")<<endl;
	cout<<"s.myAtoi(\"9223372036854775808\")的结果是:"<<s.myAtoi("9223372036854775808")<<endl;
	cout<<"s.myAtoi(\"0-1\")的结果是:"<<s.myAtoi("0-1")<<endl;
	cout<<"s.myAtoi(\".1\")的结果是:"<<s.myAtoi(".1")<<endl;
}

执行结果:
在这里插入图片描述

java版答案

package mavenDemo;

class Solution {
	public int myAtoi(String str) {
		// null or empty string
		String s = str;
		if (s == null || s.length() == 0)
			return 0;

		// 去空格,只去前后空格
		s = s.trim();

		// 此处非常有必要在验证一次s是否为空
		if (s == null || s.length() == 0)
			return 0;
		
		// 判断正负号
		boolean sign = true;
		int i = 0;
		char signChar = s.charAt(i);
		if (signChar == '+') {
			i++;
		} else if (signChar == '-') {
			sign = false;
			i++;
		}

		// 计算真实值
		long tmp = 0;
		for (; i < s.length(); i++) {
			int digit = s.charAt(i) - '0';// 将字符转换为数字
			if (digit < 0 || digit > 9)
				break;
			if (sign) {
				tmp = tmp * 10 + digit;
				if (tmp > Integer.MAX_VALUE)
					return Integer.MAX_VALUE;
			} else {
				tmp = tmp * 10 - digit;
				if (tmp < Integer.MIN_VALUE)
					return Integer.MIN_VALUE;
			}
		}

		return (int) tmp;
	}
}

public class Test {
	public static void main(String[] args) {
		Solution s = new Solution();
		System.out.println("s.myAtoi(\"42\")的结果是:"+s.myAtoi("42"));
		System.out.println("s.myAtoi(\"-42\")的结果是:"+s.myAtoi("-42"));
		System.out.println("s.myAtoi(\"4193 with words\")的结果是:"+s.myAtoi("4193 with words"));
		System.out.println("s.myAtoi(\"words and 987\")的结果是:"+s.myAtoi("words and 987"));
		System.out.println("s.myAtoi(\"-91283472332\")的结果是:"+s.myAtoi("-91283472332"));
		System.out.println("s.myAtoi(\"  0000000000012345678\")的结果是:"+s.myAtoi("  0000000000012345678"));
		System.out.println("s.myAtoi(\"+-2\")的结果是:"+s.myAtoi("+-2"));
		System.out.println("s.myAtoi(\"-000000000000001\")的结果是:"+s.myAtoi("-000000000000001"));
		System.out.println("s.myAtoi(\"010\")的结果是:"+s.myAtoi("010"));
		System.out.println("s.myAtoi(\"9223372036854775808\")的结果是:"+s.myAtoi("9223372036854775808"));
		System.out.println("s.myAtoi(\"0-1\")的结果是:"+s.myAtoi("0-1"));
		System.out.println("s.myAtoi(\".1\")的结果是:"+s.myAtoi(".1"));
		System.out.println("s.myAtoi(\"+2323 11\")的结果是:"+s.myAtoi("2323 11"));
		System.out.println("s.myAtoi(\" \")的结果是:"+s.myAtoi(" "));
	}
}

执行结果
在这里插入图片描述

python版答案

# coding: utf-8

import re
class Solution:
    def myAtoi(self, str):
        if not str :
            return 0
        str = str.strip()#去空
        out = re.search(r"[+-]?\d+",str)
        print(out)
        if out:
            s = out.start()
            e = out.end()
            #\D匹配一个非数字字符,上面的正则匹配的数字out,str在out前面还有非数字字符则返回0
            if re.search(r"[\D]+",str[:s]):
                return 0
            i = int(str[s:e])
            if i > 2**31 - 1:
                return 2**31 - 1
            if i < -2**31:
                return -2**31
            
            return i
        return 0
        
        
############    主程序   ##############
if __name__ == "__main__":
    s = Solution()
    print( "s.myAtoi(\"-42\")的结果是:"+ str(s.myAtoi("-42")));
    print( "s.myAtoi(\"words and 987\")的结果是:"+ str(s.myAtoi("words and 987")));
    print( "s.myAtoi(\"42\")的结果是:"+ str(s.myAtoi("42")));
    print( "s.myAtoi(\"4193 with words\")的结果是:"+ str(s.myAtoi("4193 with words")));
    print( "s.myAtoi(\"-91283472332\")的结果是:"+ str(s.myAtoi("-91283472332")));
    print( "s.myAtoi(\"  0000000000012345678\")的结果是:"+ str(s.myAtoi("  0000000000012345678")));
    print( "s.myAtoi(\"+ str(-2\")的结果是:"+ str(s.myAtoi("+ str(-2")));
    print( "s.myAtoi(\"-000000000000001\")的结果是:"+ str(s.myAtoi("-000000000000001")));
    print( "s.myAtoi(\"010\")的结果是:"+ str(s.myAtoi("010")));
    print( "s.myAtoi(\"9223372036854775808\")的结果是:"+ str(s.myAtoi("9223372036854775808")));
    print( "s.myAtoi(\"0-1\")的结果是:"+ str(s.myAtoi("0-1")));
    print( "s.myAtoi(\".1\")的结果是:"+ str(s.myAtoi(".1")));
    print( "s.myAtoi(\"+ str(2323 11\")的结果是:"+ str(s.myAtoi("2323 11")));
	print( "s.myAtoi(\" \")的结果是:"+ str(s.myAtoi(" ")));

执行结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/chekongfu/article/details/82917876