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}