Last Updated: 2023-11-29 02:23:42 Wednesday
-- TOC --
反转整数,返回值也是整数。
整数默认是signed,在申明时,如果需要unsigned,反而是需要将unisgned写出来。很多时候我们使用int32_t或uint32_t这类定义,容易忽略了默认signed的事实!
Given a signed 32-bit integer x, return x with its digits reversed. If reversing x causes the value to go outside the signed 32-bit integer range \([-2^{31}, 2^{31} -1]\), then return 0. Assume the environment does not allow you to store 64-bit integers (signed or unsigned).
输入一个32位的signed integer,按位反转,保持符号不变,去掉反转后前面的0,如果反转后的数字overflow,返回0。要求不允许使用64位整数。(这个要求对Python无效,这个地方也是用C/C++的难点,如何判断溢出)
Example 1:
Input: x = 123
Output: 321
Example 2:
Input: x = -123
Output: -321
Example 3:
Input: x = 120
Output: 21
没啥算法,按照题意直接写,利用slicing操作反转:(Python这样的高高级语言,没有unsigned的概念)
class Solution:
def reverse(self, x: int) -> int:
a = int(str(abs(x))[::-1]) * (1 if x>=0 else -1)
return a if -0x80000000<=a<0x80000000 else 0
这个Python版本,又短又快!
Python骚操作不一定快,只是骚:
$ python -m timeit -p -s 's=1;a=1234' '(-a,a)[s==1]'
5000000 loops, best of 5: 55.5 nsec per loop
$ python -m timeit -p -s 's=1;a=1234' 'a if s==1 else -a'
20000000 loops, best of 5: 19.9 nsec per loop
在拼装反转int的过程中,及时判断是否溢出。Python的实现作为参考,主要看C/C++的实现和速度。
class Solution:
def reverse(self, x: int) -> int:
sign = 1 if x>=0 else -1
x = abs(x)
a = 0
if x//(10**9) == 0:
while x:
a = a*10 + x%10
x //= 10
else:
ob = (2,1,4,7,4,8,3,6,4)+((7,) if sign==1 else (8,))
edge = True
for i in range(10):
b = x % 10
if edge:
if b < ob[i]:
edge = False
elif b > ob[i]:
return 0
a = a*10 + b
x //= 10
return sign * a
发现一个细节,Python代码中那些作为常量的顺序结构,用tuple的速度比list快很多:
$ python -m timeit -p '(1,2,3,4,5)'
50000000 loops, best of 5: 6.64 nsec per loop
$ python -m timeit -p '[1,2,3,4,5]'
5000000 loops, best of 5: 43.3 nsec per loop
$ python -m timeit -p '(1,2,3,4,5)+(6,7,8)'
50000000 loops, best of 5: 6.59 nsec per loop
$ python -m timeit -p '[1,2,3,4,5]+[6,7,8]'
2000000 loops, best of 5: 105 nsec per loop
class Solution {
public:
int reverse(int x) {
if(x == 0x80000000)
return 0;
int mask { x>>31 };
int sign { (x!=0)|mask };
x = (x^mask) - mask;
int a {};
if(x/1000000000 == 0)
while(x){
a = a*10 + x%10;
x /= 10;
}
else{
vector<int> obits {2,1,4,7,4,8,3,6,4,7};
obits[9] -= mask;
bool overflow {true};
for(int i{}; i<10; ++i){
int b {x % 10};
if(overflow){
if(b > obits[i])
return 0;
else if(b < obits[i])
overflow = false;
}
a = a*10 + b;
x /= 10;
}
}
return sign * a;
}
};
开头直接处理唯一的一种特殊情况,因为这个最大的负数做abs是不合适的。请看下面示例:
#include <iostream>
using namespace std;
int main(void) {
int a { (int)0x80000000 };
int b { a+1 };
a = abs(a);
b = abs(b);
cout << a << endl;
cout << b << endl;
return 0;
}
这段测试代码输出如下:
-2147483648
2147483647
对32位最大的负数做abs没有任何效果。更多:位运算的妙用和坑
int reverse(int x){
if(x == 0x80000000)
return 0;
int mask = x >> 31; // 0, -1
int sign = (x!=0)|mask; // -1, 0, 1
x = (x^mask) - mask; // abs
int a = 0;
if(x/1000000000 == 0)
while(x){
a = a*10 + x%10;
x /= 10;
}
else{
int obits[10] = {2,1,4,7,4,8,3,6,4,7};
obits[9] -= mask; // +0, +1
bool overflow = true;
for(int i=0; i<10; ++i){
int b = x % 10;
if(overflow){
if(b > obits[i])
return 0;
else if(b < obits[i])
overflow = false;
}
a = a*10 + b;
x /= 10;
}
}
return sign * a;
}
int reverse(int x){
int r = 0;
while(x){
if(r>INT_MAX/10 || r<INT_MIN/10)
return 0;
r = r*10 + x%10;
x /= 10;
}
return r;
}
这段代码为什么OK?因为当x为负数的时候,x%10
可以得到负值。具体请参考:模运算(求余)的坑。这个算法仅C/C++,Python没有缘分。我喜欢这个简单简洁的算法!
本文链接:https://cs.pynote.net/ag/leetcode/202212051/
-- EOF --
-- MORE --