Skip to content

Commit bd19053

Browse files
committed
LeetCode 7. Reverse Integer
1 parent f21c3c9 commit bd19053

File tree

3 files changed

+124
-1
lines changed

3 files changed

+124
-1
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Solutions to LeetCode problems. The first column links to the problem in LeetCod
2121
| [3. Longest Substring Without Repeating Characters][lc3] | 🟠 Medium | [![python](res/py.png)](leetcode/longest-substring-without-repeating-characters.py) |
2222
| [5. Longest Palindromic Substring][lc5] | 🟠 Medium | [![python](res/py.png)][lc5py] |
2323
| [6. Zigzag Conversion][lc6] | 🟠 Medium | [![python](res/py.png)][lc6py] |
24+
| [7. Reverse Integer][lc7] | 🟠 Medium | [![python](res/py.png)][lc7py] |
2425
| [11. Container With Most Water][lc11] | 🟠 Medium | [![python](res/py.png)][lc11py] |
2526
| [12. Integer to Roman][lc12] | 🟠 Medium | [![python](res/py.png)][lc12py] |
2627
| [13. Roman to Integer][lc13] | 🟢 Easy | [![python](res/py.png)][lc13py] |
@@ -306,6 +307,8 @@ Solutions to LeetCode problems. The first column links to the problem in LeetCod
306307
[lc5py]: leetcode/longest-palindromic-substring.py
307308
[lc6]: https://leetcode.com/problems/zigzag-conversion/
308309
[lc6py]: leetcode/zigzag-conversion.py
310+
[lc7]: https://leetcode.com/problems/reverse-integer/
311+
[lc7py]: leetcode/reverse-integer.py
309312
[lc11]: https://leetcode.com/problems/container-with-most-water/
310313
[lc11py]: leetcode/container-with-most-water.py
311314
[lc12]: https://leetcode.com/problems/integer-to-roman/

leetcode/lists/neetcode.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ From their website:
545545
||| 🟢 Easy | [190. Reverse Bits][lc190] | [![python](../../res/py.png)][lc190py] |
546546
||| 🟢 Easy | [268. Missing Number][lc268] | [![python](../../res/py.png)][lc268py] |
547547
||| 🟠 Medium | [371. Sum of Two Integers][lc371] | [![python](../../res/py.png)][lc371py] |
548-
| | | 🟠 Medium | [7. Reverse Integer][lc7] | |
548+
| | | 🟠 Medium | [7. Reverse Integer][lc7] | [![python](../../res/py.png)][lc7py] |
549549

550550
[lc136]: https://leetcode.com/problems/single-number/
551551
[lc136py]: ../single-number.py
@@ -560,4 +560,5 @@ From their website:
560560
[lc371]: https://leetcode.com/problems/sum-of-two-integers/
561561
[lc371py]: ../sum-of-two-integers.py
562562
[lc7]: https://leetcode.com/problems/reverse-integer/
563+
[lc7py]: ../reverse-integer.py
563564
[neetcode]: https://neetcode.io

leetcode/reverse-integer.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# 7. Reverse Integer
2+
# 🟠 Medium
3+
#
4+
# https://leetcode.com/problems/reverse-integer/
5+
#
6+
# Tags: Math
7+
8+
import timeit
9+
10+
11+
# Decompose the input into its constituent digits, then reverse them and
12+
# construct a value that has all digits at their corresponding place, to
13+
# do that, we can use the fact that we are using base 10 and multiply
14+
# each number by 10^i where i is its order in the resulting digit.
15+
#
16+
# Time complexity: O(n) - With n the number of digits in the input or
17+
# O(log(n)) with n the value of the input, at each iteration of the
18+
# loop we divide this value by 10.
19+
# Space complexity: O(n) - With n the number of digits in the input, we
20+
# store a list of the input's value digits.
21+
#
22+
# Runtime: 72 ms, faster than 16.21%
23+
# Memory Usage: 13.9 MB, less than 64.41%
24+
class ByDigits:
25+
def reverse(self, x: int) -> int:
26+
# Work with the absolute value.
27+
num = abs(x)
28+
# Split the number into its digits.
29+
digits = []
30+
while num > 0:
31+
num, digit = divmod(num, 10)
32+
digits.append(digit)
33+
# 2^31 with its last digit chopped off, we use this value to
34+
# check overflow because we are reconstructing the reversed
35+
# integer from most significant to least significant digit.
36+
MAX = 147483648
37+
res = 0
38+
power = 1
39+
# Start adding the digits at their corresponding place.
40+
# 12345 => 1 * 10_000 + 2 * 1_000 + 3 * 100 + 4 * 10 + 5 * 1
41+
for digit in reversed(digits):
42+
# Check if adding this digit at the start of this value
43+
# would overflow.
44+
if ((x > 0 and res >= MAX) or (x < 0 and res > MAX)) and digit > 1:
45+
return 0
46+
res += digit * power
47+
power *= 10
48+
# Remember to add the sign if needed.
49+
return res if x >= 0 else -res
50+
51+
52+
# Same logic as the previous version but merge the two loops into one.
53+
#
54+
# Time complexity: O(log(n)) - Where n is the value of the input x, for@
55+
# each iteration of the input we divide the value by 10, the loop will
56+
# run log(n) times.
57+
# Space complexity: O(1) - We only use constant space besides input and
58+
# output values.
59+
#
60+
# Runtime: 57 ms, faster than 60.21%
61+
# Memory Usage: 13.8 MB, less than 97.07%
62+
class OneLoop:
63+
def reverse(self, x: int) -> int:
64+
# 2^31 // 10
65+
MAX = 214748364
66+
num = abs(x)
67+
res = 0
68+
while num:
69+
# Pop the last digit.
70+
num, digit = divmod(num, 10)
71+
# Check if adding the current digit would result in integer
72+
# overflow using 32 bit integers. We check both negative and
73+
# positive integer overflow depending on the sign of x.
74+
if res > MAX or (
75+
res == MAX and ((x > 0 and digit > 7) or (x < 0 and digit > 8))
76+
):
77+
return 0
78+
# If safe, add the current digit to the reversed integer.
79+
res = res * 10 + digit
80+
# Readd the sign and return the reversed integer.
81+
return res if x >= 0 else -res
82+
83+
84+
def test():
85+
executors = [
86+
ByDigits,
87+
OneLoop,
88+
]
89+
tests = [
90+
[0, 0],
91+
[120, 21],
92+
[123, 321],
93+
[-123, -321],
94+
[8463847412, 0], # MAX_INT + 1
95+
[1534236469, 0],
96+
[-9463847412, 0], # MIN_INT - 1
97+
[1463847412, 2147483641],
98+
[7463847412, 2147483647], # Max positive value when reversed.
99+
[-8463847412, -2147483648], # Max negative value when reversed.
100+
]
101+
for executor in executors:
102+
start = timeit.default_timer()
103+
for _ in range(1):
104+
for col, t in enumerate(tests):
105+
sol = executor()
106+
result = sol.reverse(t[0])
107+
exp = t[1]
108+
assert result == exp, (
109+
f"\033[93m» {result} <> {exp}\033[91m for"
110+
+ f" test {col} using \033[1m{executor.__name__}"
111+
)
112+
stop = timeit.default_timer()
113+
used = str(round(stop - start, 5))
114+
cols = "{0:20}{1:10}{2:10}"
115+
res = cols.format(executor.__name__, used, "seconds")
116+
print(f"\033[92m» {res}\033[0m")
117+
118+
119+
test()

0 commit comments

Comments
 (0)