一起學Rust-實戰leetcode(五)

  • 2019 年 10 月 7 日
  • 筆記

微信關注公眾號 [可回收BUG]

上期練習:一起學Rust-實戰leetcode(四)

給出一個 32 位的有符號整數,你需要將這個整數中每位上的數字進行反轉。

示例 1:

輸入: 123  輸出: 321

示例 2:

輸入: -123  輸出: -321

示例 3:

輸入: 120  輸出: 21

注意:

假設我們的環境只能存儲得下 32 位的有符號整數,則其數值範圍為 [−2^31, 2^31 − 1]。請根據這個假設,如果反轉後整數溢出那麼就返回 0。

來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/reverse-integer

這是來源於leetcode的一道題 「整數反轉」,我們使用Rust來實現。

本次實戰目的:

對 Option<T> 的取值函數的複習,與數字溢出的情況處理。

簡單分析:

題目需要將數字反轉過來,並保留當前的符號,數字類型是 i32 ,範圍是[2147483647,-2147483648]。

對於數字的每一位可以通過不斷對數字以10為除數取余和對剩下的數字被10整除的商再次進行取余,便可以依次取取出各位數字。

例如:

x = 123,

x % 10 = 3,x = floor(x / 10) = 12,

x % 10 = 2,x = floor(x/10) = 1,

x % 10 = 1。x = floor(x/10) = 0,停止。

分別依次得到3,2,1。

剛好第一個就可以獲得目標結果數字的第一個,那麼每次將其當前總結果乘10後與計算結果相加:

ret = 0

x % 10 = 3,ret = ret * 10 + 3 = 3

x % 10 = 2,ret = ret * 10 + 2 = 30 + 2

x % 10 = 1,ret = ret * 10 + 1 = 320 + 1

下面看一下程式碼:

fn reverse(x: i32) -> i32 {      let mut x = x;      let mut result:Option<i32> = Some(0);        loop {          if x == 0 {              break;          }          let tmp_num = x % 10;          x = x / 10;            result = result.unwrap().checked_mul(10);          if result.is_none() {              return 0_i32;          }            result = tmp_num.checked_add(result.unwrap());          if result.is_none() {              return 0_i32;          }      }        result.unwrap()  }

解釋:

checked_mul(y) 乘法,可以由數字或者數字變數直接調用,需要明確數字類型,此函數結果會返回Option<T>類型,溢出範圍則返回None。

checked_add(y) 加法,溢出後返回None。

unwrap() 獲取枚舉內的值,會獲取枚舉變數的所有權。

注意:

用IDE書寫程式碼時,checked_mul 和 checked_add 並沒有提示,我們看一下 i32 的方法實現:

#[lang = "i32"]  impl i32 {      int_impl! { i32, i32, u32, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301",          "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",          "[0x12, 0x34, 0x56, 0x78]", "", "" }  }

i32 定義的方法內部是通過 int_impl! 宏展開的方法。int_impl! 宏內對checked_mul 定義了文檔、文檔內測試和方法體。

doc_comment! {              concat!("Checked integer multiplication. Computes `self * rhs`, returning `None` if  overflow occurred.    # Examples    Basic usage:    ```  ", $Feature, "assert_eq!(", stringify!($SelfT),  "::max_value().checked_mul(1), Some(", stringify!($SelfT), "::max_value()));  assert_eq!(", stringify!($SelfT), "::max_value().checked_mul(2), None);",  $EndFeature, "  ```"),              #[stable(feature = "rust1", since = "1.0.0")]              #[must_use = "this returns the result of the operation,                             without modifying the original"]              #[inline]              pub fn checked_mul(self, rhs: Self) -> Option<Self> {                  let (a, b) = self.overflowing_mul(rhs);                  if b {None} else {Some(a)}              }          }

文件:share/rust/rust_src/libcore/num/mod.rs