image.png
1. 总结
一拿到该题的时候,首先想到的便是for循环遍历然后进行反转。因为题目中重点强调了边界范围,所以在实现的过程中使用for循环获取到2^31的值。
写的比较坎坷,总体来说写完后的bug主要是:
1. for循环获取2^31时
int bj = 1;
for (int i = 0; i < 32; i++) {
bj = 2 * bj;
}
问题出在哪里?
- 2^0为1,但是当i=0时,bj=2;故循环要在int i=1开始;
- 当bj为int类型,且bj=
2^31
时,由于int的范围[-2^31,2^31-1]
,那么bj实际的值为-2^31
。
修改方案:使用
Integer.MAX_VALUE
和Integer.MIN
来获取边界值;
2. 使用for循环实现整数反转后,得到反转的值存在越界问题;
修改方案:使用long来存储值,强转为int后,判断和long类型的关系;
3. 反转后的正负号问题;
设置标识位
1.1 如何确定int边界
为了防止int类型越界导致转换异常,故使用long类型来进行全局处理。在返回结果时,需要将long强转为int类型。
- 当long强转前和强转后的值不同时(证明丢失精度),那么表示越界,按照题目描述返回0;
- 否则的话,返回强转后的值;
1.2 字符串反转思路
/**
* 解答成功:
* 执行耗时:14 ms,击败了5.74% 的Java用户
* 内存消耗:38.2 MB,击败了5.00% 的Java用户
*/
public int reverse(int x) {
//1. x进入后转换为long类型
long xl = Integer.valueOf(x).longValue();
int end = xl < 0 ? 1 : 0;
String s = xl + "";
char[] chars = s.toCharArray();
String r = xl < 0 ? "-" : "";
//反转
for (int i = chars.length - 1; i >= end; i--) {
r = r + chars[i];
}
//强转
Long l = r == "" ? 0 : Long.valueOf(r);
int i = l.intValue();
if (l > i || l < i) {
return 0;
} else {
return i;
}
}
1.3 leetcode牛人思路
整数反转可看做入栈和出栈的过程,全程使用取余操作,获取整数的最后一个数字(完成出栈)。将出栈的数字入栈则做乘10操作。
注意点:
- 反转后的值存在越界风险,使用long来进行操作;
- 负数的除操作得到的商为负数,取余操作得到的余数也是负数;
/**
* 整数转换通过除与取余的方式
* <p>
* 0 -> 0
* 12 -> 1 2 | 0 1
* 123 -> (123)12 3 |(12) 1 2 |(1) 0 1
* 1234 -> (1234) 123 4 |(123) 12 3 | (12) 1 2 | 0 1
* <p>
* <p>
* -1 -> 0 -1
* -12 -> (12) -1 -2| (-1) 0 -1
*/
最终代码:
/**
* 借助除与取余进行反转
* <p>
* 执行耗时:1 ms,击败了100.00% 的Java用户
* 内存消耗:35.7 MB,击败了25.79% 的Java用户
*/
public int reverse(int x) {
if (x == 0) {
return 0;
}
//转换
Long r = 0L;
while (x != 0) {
r = 10 * r + x % 10;
x = x / 10;
}
int i = r.intValue();
return i > r || i < r ? 0 : i;
}
2. 回文数
力扣题目:9. 回文数
虽然题目不同,但是思路相同,利用除与取余实现的整数反转,反转后的整数和原整数进行判断。
public boolean isPalindrome(int x) {
if (x < 0) {
return false;
}
//整数反转思维
int source = x;
long l = 0;
while (x != 0) {
l = l * 10 + x % 10;
x = x / 10;
}
return l == source;
}
网友评论