一起学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