leetcode_rust/problems/p000_0xx/p000_007.rs
1//! # Description
2//!
3//! Given a signed 32-bit integer `x`, return `x` with its digits reversed.
4//! If reversing `x` causes the value to go outside the signed 32-bit integer
5//! range $[-2^{31}, 2^{31} - 1]$, then return 0.
6//!
7//! Assume the environment does not allow you to store 64-bit integers (signed
8//! or unsigned).
9//!
10//!
11//! | Example 1 |
12//! | :-- |
13//! | Input: x = 123 |
14//! | Output: 321 |
15//!
16//! | Example 2 |
17//! | :-- |
18//! | Input: x = -123 |
19//! | Output: -321 |
20//!
21//! | Example 3 |
22//! | :-- |
23//! | Input: x = 120 |
24//! | Output: 21 |
25//!
26//!
27//! Constraints:
28//!
29//! - $-2^{31} \leqslant x \leqslant 2^{31} - 1$
30//!
31//! Source: <https://leetcode.com/problems/reverse-integer/description/>
32
33////////////////////////////////////////////////////////////////////////////////
34
35/// Reverse an integer (32-bit long) and check for overflow.
36///
37/// Exchange front and end digits (not bits) one by one, return zero if
38/// overflow
39///
40/// # Argument
41/// * `x` - 32-bit signed integer to alter
42///
43/// # Examples
44/// ```
45/// use leetcode_rust::problems::p000_0xx::p000_007::reverse_integer;
46/// assert_eq!(reverse_integer(-2147483647), 0);
47/// assert_eq!(reverse_integer(123), 321);
48/// assert_eq!(reverse_integer(120), 21);
49/// assert_eq!(reverse_integer(-123), -321);
50/// ```
51pub fn reverse_integer(x: i32) -> i32 {
52 reverse_s1(x)
53}
54
55/// Reverse an integer (32-bit long) and check for overflow.
56///
57/// # Argument
58/// * `x` - 32-bit signed integer to alter
59fn reverse_s1(x: i32) -> i32 {
60 let mut temp_stack: Vec<u8> = vec![];
61 // Convert integer to digits.
62 for ch in x.to_string().as_bytes() {
63 if *ch != 45 {
64 temp_stack.push(*ch);
65 }
66 }
67 loop {
68 // Remove trailing zeros if present
69 match temp_stack.last() {
70 Some(last_ch) => {
71 if *last_ch == 48 && temp_stack.len() > 1 {
72 temp_stack.pop();
73 } else {
74 break;
75 }
76 }
77 None => break,
78 }
79 }
80 temp_stack.reverse();
81
82 // 2147483647 for positive numbers
83 let mut overflow_at_u8: [u8; 10] = [50, 49, 52, 55, 52, 56, 51, 54, 52, 55];
84 let mut target: Vec<u8> = vec![];
85 // Detect sign of input number and update overflow threshold if needed.
86 if x < 0 {
87 target.push('-' as u8);
88
89 // 2147483648 for negative numbers (without sign)
90 overflow_at_u8 = [50, 49, 52, 55, 52, 56, 51, 54, 52, 56];
91 }
92
93 // Check overflow regardless of the sign
94 if temp_stack.len() >= overflow_at_u8.len() {
95 for idx in 0..overflow_at_u8.len() {
96 if temp_stack[idx] < overflow_at_u8[idx] {
97 // If current digit is smaller than overflow threshold, no
98 // need to test anymore.
99 break;
100 }
101 if temp_stack[idx] > overflow_at_u8[idx] {
102 // Previous digit (if exists) same between target and threshold,
103 // If current digit of target is greater than threshold, then
104 // overflow.
105 return 0;
106 }
107 }
108 }
109 // Combine sign and digits
110 target = [target, temp_stack].concat();
111 String::from_utf8(target).unwrap().parse::<i32>().unwrap()
112}