一. Reverse Integer
Reverse digits of an integer.
Note:
The input is assumed to be a 32-bit signed integer. Your function should return 0 when the reversed integer overflows.
Example:
x = 123, return 321
x = -123, return -321
Difficulty:Easy
解法一
数字和字符串之间可以相互转换,如果可以反转字符串,那当然也可以反转数字。第一种解法就是将数字变为字符串,然后反转字符串,最后再变回数字,不过要多加一个对负号的判定。还有就是要判定数字是否超出了 int 类型的范围,这里是在程序中计算了 int 类型的边界。不过这种解法依赖于C++的库。
int reverse(int x) {
string s = to_string(x);
int len = s.size();
char tmp;
int index = 0;
if (s[0] == '-') {
index++;
}
for (int i = len - 1; i >= (len + index) / 2; i--) {
tmp = s[i];
s[i] = s[len - 1 - i + index];
s[len - 1 - i + index] = tmp;
}
long result = stol(s);
if (result > pow(2, 31) - 1 || result < -pow(2, 31))
result = 0;
return (int)result;
}
代码的时间复杂度为 O(n) 。
优化
以上的代码存在一些问题,列举如下:
- 其实并不需要将数字转为字符串,因为如果用数字来直接反转的话,代码应该会更加简洁,因为不需要判定负号。
- 另外就是判断结果是否超出 int 类型边界,不需要在程序中算出 int 类型的上下界,因为C和C++已经定义了很多库和变量表示这些东西。
解法二
下面是优化过后的代码。这里通过一个递归表达式,可以很方便地将数字反转。
int reverse(int x) {
long result = 0;
while(x) {
result = 10 * result + x % 10;
x /= 10;
}
if(result > INT32_MAX || result < INT32_MIN)
result = 0;
return (int)result;
}
代码的时间复杂度为 O(n) 。
总结
现在把写代码遇到的问题总结一下:
unsigned类型的比较
我们都知道,容器调用 size() 函数返回的是 size_t 的类型,这是一个无符号的整形变量。因为是无符号的,所以比较的时候要格外小心。比如:
unsigned int i = 0;
cout << (i < -1) << endl; //1
cout << i - 1 << endl; //4294967295
不管是比较的时候,还是做算术运算的时候,C++都倾向于把数值往大的数据类型转换,这里也不例外。因此当判断一个无符号整形是否小于一个负数的时候,程序是先将负数提升为无符号的整形,然后再比较,因此结果一般都是 true ,与我们的预期相差甚远。因此,一定要注意不要将无符号的变量和负数以及可能出现负数的变量进行比较,也不能让无符号的变量减去一个可能大于自身的数字。
C中保存内置类型大小上限的变量
其中 int 类型的变量上限定义在 stdint.h 的头文件中(应该是默认包含的),列举如下:
#define INT8_MIN (-127i8 - 1)
#define INT16_MIN (-32767i16 - 1)
#define INT32_MIN (-2147483647i32 - 1)
#define INT64_MIN (-9223372036854775807i64 - 1)
#define INT8_MAX 127i8
#define INT16_MAX 32767i16
#define INT32_MAX 2147483647i32
#define INT64_MAX 9223372036854775807i64
#define UINT8_MAX 0xffui8
#define UINT16_MAX 0xffffui16
#define UINT32_MAX 0xffffffffui32
#define UINT64_MAX 0xffffffffffffffffui64
C++中保存内置类型信息的类