一、题目描述
原题连接: NC57 反转数字
题目描述:
给定一个32位的有符号整数num,将num中的数字部分反转,最后返回反转的结果
1.只反转数字部分,符号位部分不反转
2.反转后整数num超过 32 位的有符号整数的范围 [−231, 231 − 1] ,返回 0
3.假设本题不允许存储 64 位整数(有符号或无符号,即C++不能使用long long ,Java不能使用long等)
数据范围:
-2^31 <= x <= 2 ^31 - 1
示例1
输入:
12
返回值:
21
示例2
输入:
-123
返回值:
-321
示例3
输入:
10
返回值:
1
示例4
输入:
1147483649
返回值:
0
二、解题
方法——数字法
1、思路解析
先通过循环把数字的每一位拆开,在计算时候每一步都判断是否溢出,若溢出就直接返回0,否则进行下一轮循环。
我们使用一个变量ans来存储最终结果
我们从末尾开始取数字,用一个变量next来存储下一位
让ans累计操作:ans = ans * 10 + next即可算出最终结果。
2、代码实现
有了以上思路,那我们写起代码来也就水到渠成了:
int reverse(int x) {
// 当x介于(-10, 10)之间时,反转后还是等于自身
if (x > -10 && x < 10) {
return x;
}
int ans = 0;
while (x) {
int next = x % 10;
ans = ans * 10 + next;
x /= 10;
}
// 进行判断
if (ans < INT_MIN || ans > INT_MAX) {
return 0;
}
return ans;
}
这样看似已经完成了,但是如果你把这段代码提交到牛客网上是,就会看到:
我们在看它的提示:
我们仔细思考之后发现,还是溢出导致的问题,那是为什么呢?不是已经在每一步都判断了是否溢出了吗?怎么还会出现溢出问题呢?
其实,我们都忽略了一点,就是当一个类型的数据要存储一个超出此类型的最大值的数的时候,就会发生“截断”。例如我们知道一个unsigned char类型的变量可存储的最大值是255,若非要让它存储253 + 8,那就只能发生截断:
也就是说存入变量的是一个比最大数要小的数字了,这时候判断就会出错了。
类似的有符号数在溢出时会变成负数也是类似的原理。
所以我们要做的应该是提前判断
因为ans每次都要乘上10,所以我们应该提前一位就判断了:
若ans为正数:
1、当出现ans > INT_MAX / 10 且还有next添加时,则一定溢出了。
2、当出现ans == INT_MAX / 10且next > 7时,则一定溢出了。(7是INT_MAX的最后一位)
若ans为负数:
1、当出现ans < INT_MIN / 10且后面还有next添加时,则一定溢出。
2、当出现ans == INT_MIN / 10且next < -8时,则一定溢出。(8是INT_MIN的最后一位)
有了以上思路,那我们在写起代码来也就水到渠成了:
int reverse(int x) {
if (x > -10 && x < 10) {
return x;
}
int ans = 0;
while (x) {
int next = x % 10;
if (ans > INT_MAX / 10 || (ans == INT_MAX / 10 && next > 7)) {
return 0;
} else if (ans < INT_MIN / 10 || (ans == INT_MIN / 10 && next < -8)) {
return 0;
}
ans = ans * 10 + next;
x /= 10;
}
return ans;
}