LeetCode :Reverse Integer

题目如上图所示,已知整型X ,实现将其所有位上的数字逆序。题目已提示需要考虑逆序过程中出现的越界问题以及x的个位为0的情况。由于不考虑越界和个位问题的情况很简单,在此就不作赘述。直接上代码(其中有个小隐患,在后面再说):

  int reverse(int x) {
        int m;
        int result=0;
        int flag=0;
        if(x==0)
            return result;
       <span style="color:#FF6666;"> if(x<0)//判断x是否是负数,如果是,标记变量flag为1,并取x的绝对值
        {
            flag=1;
            x=abs(x);
        }</span>
        while(x!=0)//从最低位开始,从右往左依次得到x上各位数字
        {
            m=x%10;//得到最低位的数字
            result=result*10+m;
            x=x/10;
           
        }
        if(flag==1)
             result=(-1)*result;
        return result;  
       
    }
        


1)个位为0的情况

   while(x%10==0)
        {
            x=x/10;//把末尾的所有0去掉
        }

2)逆序过程中出现的越界问题

首先我们需要对x为正数还是负数分开讨论。题目中给出的运行环境是32-bit,则int 的取值范围为-2^31~2^31-1。

PS:这里先补充点整型的存储知识。我们知道数字是采用二进制的形式存储在计算机中的。若运行环境为32bit则表示int的大小为32bit,即一个int类型的数采用32位二进制表示。其中最高位作为符号位,0表示正数,1表示负数。数字可以表示成原码、反码、补码。原码即最高位表示符号位,0~30位表示数值的大小,若采用原码的形式存储在计算机中,会发现有两个0,:正0和负0,这显然限制了存储范围。于是,采用补码存储数字。对于正数,原码与补码相同,而对于负数,需要把负数的原码中除符号位之外的各位数取反加1。采用补码的方式存储,“负0”则表示最小的负数。这样,最小负数的绝对值比最大正数大1。也可以采用另一种方式理解,负数和正数的个数是相同的,然而0占用了正数的名额,于是正数最大值就比最小负数的绝对值少1。

a)当x为正数时:每次需要判断result*10+m的值是否已经越界,若越界,则直接终止程序,返回0。若单纯采用result*10+m<2147483647 ,则会出现在result*10过程中出现的溢出问题。由于运行环境是32bit,int和long表达的数值范围是相同的(16位环境中long是8字节)。于是将result*10强制转换为long long。这里可能会有人有疑问为什么不能用unsigned int。这是因为unsigned int 的最大值也只有2^32 -1,x的值若为2147483647,则当result=74638471时,result*10溢出。

b)当x为负数时:在开头提到原代码中对负数的处理存在隐患,这个隐患是在取x的绝对值上。若x为最小负数,-2147483648,若其绝对值2147483648显然是溢出,执行abs(x)后得到的结果仍然是-2147483648。有人会想到将x转换成long long ,再执行abs()函数,这显然是不可取的,因为int 转换成long long 过程中,高位补符号位,若采用这种方式,在之后的逆序过程中会无意增加了x的位数。

那我们若强制转换成unsigned int呢?首先,负数转换成unsigned int>正数转换成unsigned int,这是因为负数的符号位为1。其次,若a<b<0,则(unsigned int) a < (unsigned int)  b (全1为-1).。 于是我们得到结论:若x<0,(unsigned int )x >=(unsigned int)2147483648 ,若x>0,(unsigned int)x<(unsigned int)2147483648。 通过这个结论,我们可以得出对于所有x>-2147483648,若(unsigned int)result*10+m>=(unsigned int)2147483648,则表示存在溢出(result*10+m值是由正溢出为负数)。而对于x=-2147483648,则一定不能实现逆序。由此,完整代码如下:

class Solution {
public:
    int reverse(int x) {
        int m;
        int result=0;
        int flag=0;
        if(x==0)
            return result;
        if(x<0)//如果x是负数,标记为-1,并取x的绝对值
        {
            flag=1;
            x=abs(x);
            //printf("%lld",x);
        }
        while(x%10==0)
        {
            x=x/10;//把末尾的所有0去掉
        }
        while(x!=0)//从最低位开始,从右往左依次得到x上各位数字
        {
            m=x%10;//得到最低位的数字
            //判断是否越界,如果x是负数,则result*10+m不能超过int负数最小值的绝对值,如果x是整数,则result*10+m不能超过int正数最大值
            if((flag==0&&(2147483647<=(long long )result*10+m))||(flag==1&&((unsigned int )2147483648<=(unsigned int)result*10+m)))
               //if((flag==0&&(2147483647<=(long long )result*10+m))||(flag==1&&((unsigned int )2147483648<=(long long )result*10+m)))
               return 0;
            else {
                result=result*10+m;
                x=x/10;
            }
                //return 0;
        }
        if(flag==1)
             result=(-1)*result;
        return result;
        
       
    }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值