题目
给出一个 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
解题思路
解决改问题主要关注两个点:
- 整数反转
- 判断反转后的整数是否还在32位有符号整数范围之内
整数反转:
就是一个小学公式做循环迭代,目的是分解出整数的各十百千等位的数字。所以这道题和回文数的判断、水仙花数都类似。
被 除 数 = 除 数 ∗ 商 + 余 数 被除数=除数*商+余数 被除数=除数∗商+余数
我的第一思路就是循环分解出整数的个十百千…的数字,一次加入集合中,然后再循环集合,分别取出数值乘相应权重,并计算总和,就得到反转后的结果。
比如:待反转的整数是123,将3,2,1分别存入集合,得到[3,2,1],然后遍历集合,计算
3
∗
100
+
2
∗
10
+
1
∗
1
3*100+2*10 + 1*1
3∗100+2∗10+1∗1,得到321。权重100,10…如何得到的呢?就是根据集合的大小确定,初始权重是10的size-1次幂,遍历一次指数减一。实现代码如下:
//1.将整数的字符提取出来
int quotient;
//余数
int remainder;
List<Integer> remainders= new ArrayList<>();
do {
quotient = x / 10;
remainder = x % 10;
x = quotient;
remainders.add(remainder);
} while (quotient > 0);
int size = remainders.size();
for(int i : remainders){
size =size-1;
result = result+ i*pow(size);
}
指数运算方法
public static int pow(int x) {
int result =1;
for(int i = 0;i<x;i++){
result = result*10;
}
return result;
}
在用代码实现自己的思路过程中,我就觉得很不对劲,虽然写完也能跑出正确结果,但是从空间复杂度和时间复杂度来说都不合格,多开辟了一个集合的空间,加了一个双层循环,这完全是没有必要的计算,这代码写的真的很蠢。其实在循环分解数字时就可以累乘和相加,代码非常简单。
判断的整数范围:
刚开始是想用Java的异常机制捕获整形溢出出错,结果发现并不会报错。所以后面就只能用long类型定义result,然后判断是否超出int类型。
正好Java的int类型就是带符号的,占用4个字节也就是32位。
代码实现
public int reverse(int x) {
//int的最大值最小值
int max = Integer.MAX_VALUE;
int min = Integer.MIN_VALUE;
//int max = 0x7fffffff, min = 0x80000000;
long result = 0;
while (x != 0) {
result = result * 10 + x % 10;
x = x/ 10;
}
if (result > max || result < min) {
return 0;
} else {
return (int) result;
}
}
总结
这是一道简单题,由于自己想的过于复杂,再饶了不少弯路之后虽然,但是代码臃肿,而且效率很低。对于算法的学习只能多学习,多思考,多借鉴,多总结。也要记录、反思自己的思考过程。