前言:这是我们大学社团给我们大一新生布置的每日一题任务,因为本人编程理解有限,参考价值较低。
先看看题目:
给你一个 32 位的有符号整数 x
,返回将 x
中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−2^31, 2^31 − 1]
,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
我使用的语言是C++,需要用class类来写这道题QAQ。
当我们看到这种反转类的题目的时候,首先就会想到要用一个while循环以字符的形式一个一个位的反转,实用又方便,但是题目中有一个恶行人的限制:
如果反转后整数超过 32 位的有符号整数的范围
[−2^31, 2^31 − 1]
,就返回 0。
说实话我看到这句话的时候整个人都不好了。也就是说这道题我们会面临一个反转数会把int给爆掉的严肃问题。那么这样我们的考点就是对c++二进制存储数字的理解了。
(能力原因,讲的比较奇怪)
这么说,我们定义一个分正负的整数的数据类型L,我们给L 5个二进制数字的储存空间
比如L=0(10)=00000(2),L=2(10)=00010(2)
其中最大的正数是L=15(10)=01111(2)
对于它的第一位,我们会用来存储负号
比如L=-1(10)=10001(2)
要注意L=10000(2)比较特殊,它的值是-16
所以对于L来说它能取到的整数区间是[-16,15],或者说:[-2^4,2^4-1]
众所周知,int的范围是[-2^31,2^31-1],也就是题目中所给出的x的范围
在做这道题的时候,负号在最后才会有用,所以我们可以先把它拿掉,再把x用long long来存储一下以防止倒过来的时候超过了int让我们看到一堆看不懂的数字:
long long a = x<0? -x:x;
然后我们无论使用while还是for都可以对a进行整数反转了(这道题难点真不是这个我不解释原理了),我选择的是装x的递归写法:
void f(long long b){
a=a*10+x%10;
if(x>9)f(x/10);
return;
}
最后我们再与范围比对一下看一下有没有超过int范围,然后就输出我们的答案。
讲一下我用了左移<<,没有学过这个的可以这么理解:1<<n==pow(2,n),这个不需要cmath库的
if(x<0)return a>((long long)1<<31) 0 : x<0 ? -a:a;
else return a>=((long long)1<<31) 0: x<0 ? -a:a;
真是一道有趣的题呢~
所以我AC的代码如下:
class Solution {
public:
long long ans;
void f(long long x){
ans=ans*10+x%10;
if(x>9)f(x/10);
return;
}
int reverse(int x) {
ans = 0;
long long a = x;
f(a<0?-a:a);
return ans>((long long)1<<31)?0:x<0?-ans:ans;
}
};
不用一个long long a去存储x的话有一个过不去,return照我这么写其实会出问题,但是它就是过了。秉怀着能跑就不重写的原则,我诚挚推荐大家别看代码,多理解理解代码上面的东西。