萌新一枚、个人记录~多多指教
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-integer
题目描述
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
示例
输入: 123 输入: -123 输入: 120
输出: 321 输出: -321 输出: 21
注意:
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为
[
−
2
31
,
2
31
−
1
]
[-2^{31},2^{31}-1]
[−231,231−1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
class Solution {
public:
int reverse(int x) {
}
};
思路
我们可以一次构建反转整数的一位数字。在这样做的时候,我们可以预先检查向原整数附加另一位数字是否会导致溢出。
反转整数的方法可以与反转字符串进行类比。
我们想重复“弹出” x x x的最后一位数字,并将它“推入”到 r e v rev rev的后面。最后, r e v rev rev 将与 x x x 相反。
要在没有辅助堆栈 / 数组的帮助下 “弹出” 和 “推入” 数字,我们可以使用数学方法。
//pop operation:
pop = x % 10;
x /= 10;
//push operation:
temp = rev * 10 + pop;
rev = temp;
但是这种方式很危险,因为当
t
e
m
p
=
r
e
v
∗
10
+
p
o
p
temp=rev * 10 +pop
temp=rev∗10+pop时会导致溢出。
幸运的是,事先检查这个语句是否会导致溢出很容易。
为了便于解释,我们假设
r
e
v
rev
rev是正数。
- 如果 t e m p = r e v ∗ 10 + p o p temp=rev*10+pop temp=rev∗10+pop导致溢出,那么一定有 r e v ≥ I N T M A X 10 rev\ge \frac{INTMAX}{10} rev≥10INTMAX
- 如果 r e v > I N T M A X 10 rev >\frac{INTMAX}{10} rev>10INTMAX,那么 t e m p = r e v ∗ 10 + p o p temp=rev*10+pop temp=rev∗10+pop一定会导致溢出。
- 如果
r
e
v
=
=
I
N
T
M
A
X
10
rev == \frac{INTMAX}{10}
rev==10INTMAX,那么只要
p
o
p
>
7
pop > 7
pop>7,
t
e
m
p
=
r
e
v
∗
10
+
p
o
p
temp=rev*10+pop
temp=rev∗10+pop就会溢出。
当 r e v rev rev为负时可以应用类似的逻辑。
class Solution {
public:
int reverse(int x) {
int rev = 0;
while (x != 0) {
int pop = x % 10;
x /= 10;
if (rev > INT_MAX/10 || (rev == INT_MAX / 10 && pop > 7)) return 0;
if (rev < INT_MIN/10 || (rev == INT_MIN / 10 && pop < -8)) return 0;
rev = rev * 10 + pop;
}
return rev;
}
};
复杂度分析
时间复杂度:
O
(
log
(
x
)
)
O(\log(x))
O(log(x)),
x
x
x 中大约有
log
10
(
x
)
\log_{10}(x)
log10(x)位数字。
空间复杂度:
O
(
1
)
O(1)
O(1)。