Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目描述:
给你一个 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
思路分析:
-
取各位的数字。
目标数字除以 10 的(目标位 - 1)次方后再用 10 取余。
比如 2345:- 最高位是千位,则除以 10 的(4 - 1)次方后为 2 ,再用 10 取余后为 2 。
- 第二高位是百位 则除以 10 的(3 - 1)次方后为 23 ,再用 10 取余后为 3 。
-
各位的数字乘以 10 的(反转后对应位 - 1)次方后累加。
如:
- 上述的 2 ,反转后的对应位是第 1 位,则是 2 乘以 10 的(1-1)次方,结果为 2 。
- 上述的 3 ,反转后的对应位是第 2 位,则是 3 乘以 10 的(2-1)次方,结果为 30 。
-
判断累加结果是否越界。
这里使用位运算进行判断。
右移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
}
总结:
-
如果环境不允许存储 64 位整数(有符号或无符号),累加结果越界时应该会发生异常,手边没有32位的机器,没有进行验证。
-
对累加结果进行位运算后进行判断,这个是用 go 的 int32 的临界值进行各种实验得出来的。
平时用不到位运算,用到的时候,实验过程还是挺有意思。