LeetCode | Reverse Integer(翻转整数)


题目:

Reverse digits of an integer.

Example1: x = 123, return 321
Example2: x = -123, return -321

click to show spoilers.

Have you thought about this?

Here are some good questions to ask before coding. Bonus points for you if you have already thought through this!

If the integer's last digit is 0, what should the output be? ie, cases such as 10, 100.

Did you notice that the reversed integer might overflow? Assume the input is a 32-bit integer, then the reverse of 1000000003 overflows. How should you handle such cases?

Throw an exception? Good, but what if throwing an exception is not an option? You would then have to re-design the function (ie, add an extra parameter).


题目不难,就是要你将整数反转显示。但是里面的问题很多,关键在于能不能将问题考虑全面。

在《剑指offer》上的面试题12:打印1到最大的n位数(这个里面只写了一种方法,书中还有另一种),也是一道数字越界的问题,通常很好的做法是设置一个数组来表示每一位。看到网上有很多人用其他方法,但是在我这里完全不能运行……也不知道什么原因。

题目中的提示信息:是否考虑了最后的若干位为0的情况;当越界了怎么办?

这些都是必须要考虑的情况,当然根据处理方法不同,正如我下面的,不存储0,但是如果输入就是0的情况,就需要另外处理了。这也是要考虑的方面。

对于将负数转化成正数,我们必须用unsigned int,那样temp才是正数,后面的运算才成立。虽然这时temp在机器中的二进制和n一样,但是temp被解析成正数。另一方面,当我们输出信息的时候,%d是以int方式输出,即使你的变量为unsigned,也可能输出成负数;同理%u以unsigned方式输出,即使你的int变量为负数!

另外,很有价值的文章补码的溢出判断与检测方法 以及 int类型取值范围

完整代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

void ReverseInteger(int n);

int main(void)
{
    int n;

    while(scanf("%d",&n) == 1){
        ReverseInteger(n);
    }

    return 0;
}

void ReverseInteger(int n)
{
    if(n==0){
        printf("0\n");
        return ;
    }

    int flag = 0;
    int arr[32] = {0};
    int len = 0;
    int remainder;
    unsigned int temp = (unsigned int)n;  //必须定义unsigned,如果为int型,对于-2147483648来说,即使取temp = -n;temp为-2147483648,以负数来表示
                            //但打印输出的时候,用%d统统解释成int型,即使变量为unsigned;同理%u解释成unsigned,即使变量为int

    if(n < 0){
        flag = 1;
        temp = (unsigned int)(-n);  //要用强制类型转换
    }
    while(temp > 0){
        remainder = temp % 10;
        temp /= 10;
        if(remainder || arr[0] != 0){
            arr[len] = remainder;
            len++;
        }
    }
    if(flag)
        printf("-");
    for(int i = 0;i < len;++i)
        printf("%d",arr[i]);
    printf("\n");
}

注意:

这道题可参考:数值的整数次方。那个地方也用到了将负数转化成正数的问题。正数转化为负数,直接加个负号即可。但负数表示的范围比正数大一,当碰到边界的时候,就会出问题。我们必须用unsigned int无符号类型来存储。并且要将n或-n强制类型转换。

代码中的temp已经是正数了,用%d打印将解析成负数(只对最大负数-2147483648来说解析成负数),用%u将解析成无符号数。其解析的都是二进制数。不管原数据是什么。比如对-1用%u打印,将变为4294967295。



题目描述: 请你来实现一个 atoi 函数,使其能将字符串转换成整数。该函数需要丢弃无用的开头空格,找到第一个非空格字符,然后将其后面的字符(如果符合要求的话)转换成整数,如果第一个非空字符为正或者负号时,将该符号与后面尽可能多的连续数字组合起来,返回整数。如果第一个非空字符是非数字字符或者一开始没有给定任何数字,则返回 0。 注意: 假如只能存储有限的整数范围内,例如32位整数,则请返回 INT_MAX(231 − 1)或 INT_MIN(−231)。 示例: 输入: "42" 输出: 42 输入: " -42" 输出: -42 解释: 第一个非空白字符为 '-', 它是一个负号。我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。 输入: "4193 with words" 输出: 4193 解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。 输入: "words and 987" 输出: 0 解释: 第一个非空字符是 'w', 但它不是数字或正、负号。因此无法执行有效的转换。 输入: "-91283472332" 输出: -2147483648 解释: 数字 "-91283472332" 超过 32 位有符号整数范围。因此返回 INT_MIN(−231)。 解题思路: 这道题比较繁琐,需要注意的地方很多,需要仔细考虑每一种情况。下面是一种比较清晰的思路: 1. 删除字符串前面的空格。 2. 判断第一个非空字符是否为正负号或数字,如果是数字则开始转换,否则直接返回0。 3. 转换过程中如果遇到非数字字符,则停止转换,返回当前已转换的数字。 4. 判断转换后的数字是否超出了32位有符号整数的范围,如果超出了则返回对应的极值。 代码实现: ```python class Solution: def myAtoi(self, str: str) -> int: # 删除字符串前面的空格 str = str.lstrip() # 判断第一个非空字符是否为正负号或数字 if not str or (not str[0].isdigit() and str[0] not in ['+', '-']): return 0 # 转换过程中如果遇到非数字字符,则停止转换 i = 1 while i < len(str) and str[i].isdigit(): i += 1 # 转换数字 num_str = str[:i] sign = -1 if num_str[0] == '-' else 1 num = 0 for c in num_str: if c.isdigit(): num = num * 10 + int(c) else: break # 判断转换后的数字是否超出了32位有符号整数的范围 max_int = 2**31 - 1 min_int = -2**31 num = num * sign if num > max_int: return max_int elif num < min_int: return min_int else: return num ``` 时间复杂度:$O(n)$,其中 $n$ 是字符串的长度。需要对字符串进行一次遍历。 空间复杂度:$O(1)$。除了常量空间之外,不需要额外的空间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值