[LeetCode][golang] 7. 整数反转

323 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目描述:

7. 整数反转

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。

如果反转后整数超过 32 位的有符号整数的范围 [−231,  231 − 1] ,就返回 0。

假设环境不允许存储 64 位整数(有符号或无符号)。

示例 1:

输入:x = 123
输出:321

示例 2:

输入:x = -123
输出:-321

示例 3:

输入:x = 120
输出:21

示例 4:

输入:x = 0
输出:0

提示:

-2 的 31次方 <= x <= 2 的 31次方 - 1

思路分析:

  1. 取各位的数字。

    目标数字除以 10 的(目标位 - 1)次方后再用 10 取余。
    比如 2345:

    • 最高位是千位,则除以 10 的(4 - 1)次方后为 2 ,再用 10 取余后为 2 。
    • 第二高位是百位 则除以 10 的(3 - 1)次方后为 23 ,再用 10 取余后为 3 。
  2. 各位的数字乘以 10 的(反转后对应位 - 1)次方后累加。

    如:

    • 上述的 2 ,反转后的对应位是第 1 位,则是 2 乘以 10 的(1-1)次方,结果为 2 。
    • 上述的 3 ,反转后的对应位是第 2 位,则是 3 乘以 10 的(2-1)次方,结果为 30 。
  3. 判断累加结果是否越界。

    这里使用位运算进行判断。
    右移31位,如果大于0,则是正数越界;如果小于-1,则是负数越界。

以 2345 为例,各位分别是 2、3、4、5,进行乘法运算后的结果为 2、30、400、5000,累加后结果为 5432 。

AC 代码:

golang :

// 整数反转
func reverse(x int) int {
   // 创建一个切片,存放 [1, 10, ..., 10 的 目标数值最大位数 次方]
   var div []int
   div = append(div, 1)
   for i := 10; ; i = i * 10 {
      // 超出最大位数,跳出循环
      if x/i == 0 {
         break
      }
      // 未超出最大位数,将 10 的位数次方添加到切片
      div = append(div, i)
   }

   sum := 0
   for i, j := len(div)-1, 0; i >= 0; i, j = i-1, j+1 {
      // 从高位获取各位的数字
      tmp := x / div[i] % 10
      // 高位的数字 乘以(反转后)对应的低位的 10 的 j 次方后,累加到结果
      // 如果环境不允许存储 64 位整数(有符号或无符号),此处应该会发生异常(未验证)。
      sum = sum + div[j]*tmp

      // 右移31位,如果大于0,则是正数越界;如果小于-1,则是负数越界。
      if sum>>31 > 0 || sum>>31 < -1 {
         return 0
      }
   }

   return sum
}

总结:

  1. 如果环境不允许存储 64 位整数(有符号或无符号),累加结果越界时应该会发生异常,手边没有32位的机器,没有进行验证。

  2. 对累加结果进行位运算后进行判断,这个是用 go 的 int32 的临界值进行各种实验得出来的。
    平时用不到位运算,用到的时候,实验过程还是挺有意思。