===问:

给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。

示例 1:

输入: 123
输出: 321

示例 2:

输入: -123
输出: -321

示例 3:

输入: 120
输出: 21

注意:

假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。

===答:

int32intint32int320

方法一:
执行用时 :0 ms/4 ms, 击败了100.00%/45.50% 的用户
内存消耗 :2.3 MB, 击败了5.56%的用户

本方法先将整数转换为字符串,获得正负符号后开始循环转换位置(和之前字符串转换的题目一样)。转换完成后合并,再变成整数返回。

func reverse2(x int) int {
	y := strings.Split(strconv.Itoa(x), "")
	i := 0

	l := len(y)

	if y[0] == "-" {
		i = 1
		l = l + 1
	}

	j := l / 2

	for ; i < j; i++ {
		y[i], y[l-1-i] = y[l-1-i], y[i]
	}

	z := ""
	for _, v := range y {
		z += v
	}

	x, _ = strconv.Atoi(z)
	// if判断语句仅针对本题中要求的返回值为32位,不要求的话本if语句可以删除
	if x > 2147483647 || x < -2147483648 {
		return 0
	}

	return x
}

方法二:
执行用时 :0 ms/4 ms, 击败了100.00%/45.5% 的用户
内存消耗 :2.2 MB, 击败了74.60%/30.95%的用户

本方法利用了数学的方法,嗯嗯,挺有意思,后面详解,还涉及到一个最大最小值衍生出的知识点。

func reverse3(x int) int {
	var y int = 0
	for x != 0 {
		y = y*10 + x%10
		x = x / 10
	}
	
	// if判断语句仅针对本题中要求的返回值为32位,不要求的话本if语句可以删除
	MAX_INT32 := int(^uint32(0) >> 1)
	MIN_INT32 := ^MAX_INT32
	//if y > 2147483647 || y < -2147483648 {
	if y > MAX_INT32 || y < MIN_INT32 {
		return 0
	}

	return y
}

===解:

只解析方法二中的三个知识点:

一、前后交替

xy
for x != 0 {
	y = y*10 + x%10
	x = x / 10
}
123
// 第一次循环
y=0*10+123%10=0+3=3
x=123/10=12

// 第二次循环
y=3*10+12%10=30+2=32
x=12/10=1

// 第三次循环
y=32*10+1%10=320+1=321
x=1/10=0

每一次循环需要实现:

xyyxxyx
y = y*10 + x%10
y*10x%10
x = x / 10xx
x / 10xx0

在未来的计算中,可能会经常用到公式一第2条和公式二第1条的思路。

二、int32最大最小值的判断

题目要求不能超出int32的范围,那么最简单做法就是直接判断int32的上下限,即

if y > 2147483647 || y < -2147483648 {
	...
}

我们这里扩展一下知识点:

uintint

1. 无符号整型uint,其最小值是0,其二进制表示的所有位都为0,

const UINT_MIN uint = 0

其最大值的二进制表示的所有位都为1,那么,

const UINT_MAX = ^uint(0)

2. 有符号整型int,根据补码,其最大值二进制表示,首位0,其余1,那么,

const INT_MAX = int(^uint(0) >> 1)

根据补码,其最小值二进制表示,首位1,其余0,那么,

const INT_MIN = ^INT_MAX

3. 本例中的语句针对int32,那么:

MAX_INT32 := int(^uint32(0) >> 1)
MIN_INT32 := ^MAX_INT32
if y > MAX_INT32 || y < MIN_INT32 {
	return 0
}
intmathfloatmath.Min(float64, float64) float64math.Max(float64, float64) float64int
func Min(x, y int64) int64 {
    if x < y {
        return x
    }
    return y
}

三、整数相除的结果

公式二第1条,为什么整数相除得到的商即是我们需要的?
因为在go中,整数相除的商为整数,且商不进行四舍五入,直接去掉小数点后面的数字。
比如:

fmt.Println(125 / 3)
fmt.Println(125 / 3.0)

// 输出:
// 41
// 41.666666666666664

由此可知,如果要让两个整数相除的商得到浮点,则只需要除数或被除数是浮点数即可。具体使用方法参考:《golang整数与小数间的加减乘除》