LeetCode(7):颠倒整数

Easy!

题目描述:给定一个范围为 32 位 int 的整数,将其颠倒。

例1:

输入:132

输出:321

例2:

输入:-123

输出:-321

例3:

输入:120

输出:21

注意:假设我们的环境只能处理 32 位 int 范围内的整数。根据这个假设,如果颠倒后的结果超过这个范围,则返回 0。

解题思路:

翻转数字问题需要注意的就是溢出问题。由于之前的OJ没有对溢出进行测试,所以网上很多人的解法没有处理溢出问题也能通过OJ。现在OJ更新了溢出测试,所以还是要考虑到。为什么会存在溢出问题呢,我们知道int型的数值范围是 -2147483648~2147483647, 那么如果我们要翻转 1000000009 这个在范围内的数得到 9000000001,而翻转后的数就超过了范围。
我最开始的想法是,用long long 型数据,其数值范围为 -9223372036854775808~9223372036854775807, 远大于int型这样就不会出现溢出问题。代码如下:

C++参考答案一:

 1 /**
 2  * Correct but can refactor the code.
 3  */
 4 class Solution {
 5 public:
 6     int reverse(int x) {
 7         long long res = 0;
 8         bool isPositive = true;
 9         if (x < 0) {
10             isPositive = false;
11             x *= -1;
12         }
13         while (x > 0) {
14             res = res * 10 + x % 10;
15             x /= 10;
16         }
17         if (res > INT_MAX) return 0;
18         if (isPositive) return res;
19         else return -res;
20     }
21 };

提交通过后,OJ给出了官方解答,一看比自己的写的更精简一些,它没有特意处理正负号,仔细一想,果然正负号不影响计算,而且没有用long long型数据,感觉写的更好一些,那么就贴出来吧:

C++参考答案二:

 1 class Solution {
 2 public:
 3     int reverse(int x) {
 4         int res = 0;
 5         while (x != 0) {
 6             if (abs(res) > INT_MAX / 10) return 0;
 7             res = res * 10 + x % 10;
 8             x /= 10;
 9         }
10         return res;
11     }
12 };

在贴出答案的同时,OJ还提了一个问题 To check for overflow/underflow, we could check if ret > 214748364 or ret < –214748364 before multiplying by 10. On the other hand, we do not need to check if ret == 214748364, why? (214748364 即为 INT_MAX / 10)

为什么不用check是否等于214748364呢,因为输入的x也是一个整型数,所以x的范围也应该在 -2147483648~2147483647 之间,那么x的第一位只能是1或者2,翻转之后res的最后一位只能是1或2,所以res只能是 2147483641 或 2147483642 都在int的范围内。但是它们对应的x为 1463847412 和 2463847412,后者超出了数值范围。所以当过程中res等于 214748364 时, 输入的x只能为 1463847412, 翻转后的结果为 2147483641,都在正确的范围内,所以不用check。

我们也可以用long long型变量保存计算结果,最后返回的时候判断是否在int返回内,参见代码如下:

C++参考答案三:

 1 class Solution {
 2 public:
 3     int reverse(int x) {
 4         long long res = 0;
 5         while (x != 0) {
 6             res = 10 * res + x % 10;
 7             x /= 10;
 8         }
 9         return (res > INT_MAX || res < INT_MIN) ? 0 : res;
10     }
11 };

下面这种方法是上面解法二的变形,其实也不难理解,因为都是用int型的,如果超出了范围,其除以10的结果就不会跟之前的结果一致,通过这点也可以进行区分,参见代码如下:

C++参考答案四:

 1 class Solution {
 2 public:
 3     int reverse(int x) {
 4         int res = 0;
 5         while (x != 0) {
 6             int t = res * 10 + x % 10;
 7             if (t / 10 != res) return 0;
 8             res = t;
 9             x /= 10;
10         }
11         return res;
12     }
13 };

基础知识回顾:

一、

INT_MIN在标准头文件limits.h中定义。

1 #define INT_MAX 2147483647
2 #define INT_MIN (-INT_MAX - 1)

在C/C++语言中,不能够直接使用-2147483648来代替最小负数,因为这不是一个数字,而是一个表达式。表达式的意思是对整数21473648取负,但是2147483648已经溢出了int的上限,所以定义为(-INT_MAX -1)。

C中int类型是32位的,范围是-2147483648到2147483647 。 
(1)最轻微的上溢是INT_MAX + 1 :结果是 INT_MIN; 
(2)最严重的上溢是INT_MAX + INT_MAX :结果是-2; 
(3)最轻微的下溢是INT_MIN - 1:结果是是INT_MAX; 
(4)最严重的下溢是INT_MIN + INT_MIN:结果是0 。

二、

求数字的绝对值,vc++提供的库函数的支持,当必须包含:#include <math.h>

其中又分好几种类型:abs、_abs64、fabs、fabsf、labs、_cabs。详细说明如下:
//Calculate the absolute value.
int abs( 
   int n 
);
long abs( 
   long n 
);   // C++ only
double abs( 
   double n 
);   // C++ only
long double abs(
   long double n
);   // C++ only
float abs(
   float n 
);   // C++ only
__int64 _abs64( 
   __int64 n 
);
//Calculates the absolute value of the floating-point argument.
double fabs( 
   double x 
);
float fabs(
   float x 
); // C++ only
long double fabs(
   long double x
); // C++ only
float fabsf( 
   float x 
);
//Calculates the absolute value of a long integer.
long labs(
      long n 
);
//Calculates the absolute value of a complex number.
double _cabs( 
   struct _complex z 
);

以上函数的原型说明来自MSDN2008,可以看出,abs()函数有很多重载形式。一般用abs()就可以满足要求(c++),其它的各种都是一些特例。

原文地址:https://www.cnblogs.com/ariel-dreamland/p/8706403.html