给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
示例 1:
输入: 123
输出: 321
示例 2:
输入: -123
输出: -321
示例 3:
输入: 120
输出: 21
注意:
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−2^31, 2^31 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
思路
看到反转,第一时间想到了栈。我的整体思路:
将数字从各位开始,依次入栈,然后再依次出栈。
需要考虑的情况:
- 末尾有0:如果末尾有0,那么最后出栈,数字前面会出现0,肯定是不行的,我用了一个flag标记第一个尾数是否为0,然后当数字依次入栈时,flag为真,且入栈的数字为0,那么zero变量+1记录尾数的0的个数,直到入栈的数字不为0,将flag置为false。出栈的时候,栈底的0就不要了,出栈数量length-zero(总数字-0个个数)。
- 判断溢出:反转过后,正数溢出后就变成231-1,负数变成-231,这两种情况需要返回0
public int reverse(int x) {
int sign = x>0?1:-1;
//一共入栈多少位
int length = 0;
//从各位开始记录有多少个零,反转的时候,这些零去除
//开始时先判断一下个位是否为0,
int zero = 0;
boolean flag = ((x%10) != 0) ? false : true;
int result = 0;
Stack<Integer> stack = new Stack<Integer>();
System.out.println(x);
while(x != 0){
int num = x % 10;
if(flag && num == 0){
zero++;
}else{
flag = false;
}
stack.push(num);
length++;
x /= 10;
}
for(int i = 0;i<length-zero;i++){
result += Math.pow(10,i) * stack.pop();
}
if(sign>0 && result==Integer.MAX_VALUE){
return 0;
}
if(sign<0 && result==Integer.MIN_VALUE){
return 0;
}
return result;
}
后来发现,根本不用考虑前面是否出现0,就算有0,java也会自动无视它。。。最后判断溢出也不需要分开考虑符号位不同的情况,可以合在一起写。优化了代码:
public int reverse(int x) {
int result = 0;
Stack<Integer> stack = new Stack<Integer>();
while(x != 0){
int num = x % 10;
stack.push(num);
x /= 10;
}
int i = 0;
while(!stack.empty()){
result += Math.pow(10,i++)*stack.pop();
}
if(result == Integer.MIN_VALUE || result == Integer.MAX_VALUE){
return 0;
}
return result;
}
执行速度从原来的的18ms提高到了10ms,效果拔群。但是还是效率远远低于官方解法,官方只花了3ms。
官方解法
官方解法使用了数学解法,没有借助栈或者数组等容器,省略了进一次栈,再出一次栈的过程,节省了时间。使用下面两个操作来模拟入栈,和出栈:
//pop operation:
pop = x % 10;
x /= 10;
//push operation:
temp = rev * 10 + pop;
rev = temp;
class Solution {
public int reverse(int x) {
int rev = 0;
while (x != 0) {
int pop = x % 10;
x /= 10;
if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0;
if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0;
rev = rev * 10 + pop;
}
return rev;
}
}