LeetCode算法题目_7
题目描述
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
解决方案
反转整数的方法可以与反转字符串进行类比。
我们想重复“弹出” xx 的最后一位数字,并将它“推入”到 \text{rev}rev 的后面。最后,\text{rev}rev 将与 xx 相反。
我的算法如下,考虑补码原码转换,不过没有加上溢出判断,并且在-2^31-1时会溢出。后续会调试更新。
int reverse(int x){
int y = x>>31;
int z = (x ^ y) - y; //取原码
int a[32];
int index = 0;
int flag = 0;
if((z & 0x80000000) != 0)
{
flag = 1;
z = z & 0x7fffffff;
}
int rev = 0;
while(z != 0)
{
int pop = z % 10;
z /= 10;
if(flag == 0)
{
if (rev > 2147483647/10 || (rev == 2147483647 / 10 && pop > 7)) return 0;
}
else
{
if (rev < 2147483648/10 || (rev == 2147483648 / 10 && pop > 8)) return 0;
}
rev = rev * 10 + pop;
}
if(flag == 1)
{
rev = rev | 0x80000000;
}
y = rev>>31;
rev = (rev ^ y) - y; //取原码
if(rev > 0xffffffff)
return 0;
else
return rev;
}
下面介绍另一种简便算法。
int reverse(int x){
/**
ret 保存旧的翻转中间值, temp 保存新的翻转过程中间值
依次提取 x 的末位加入 temp, 如果发生溢出则通过temp/10
无法得到上一轮的翻转结果 ret
**/
int ret = 0;
while(x != 0) {
long temp1 = ((long)ret*10) + x%10;
int temp = (int)temp1;
if(temp / 10 != ret)
return 0;
ret = temp;
x /= 10;
}
return ret;
}
此方法会产生溢出由于该语句有可能造成int类型超限,故强制转换ret为long。ong temp1 = ((long)ret*10) + x%10;该算法思路很简洁。
下面介绍标准算法。
int reverse(int x){
int z =x;
int rev = 0;
while(z != 0)
{
int pop = z % 10;
z /= 10;
if (rev > 2147483647/10 || (rev == 2147483647 / 10 && pop > 7)) return 0;
if (rev < -2147483648/10 || (rev == -2147483648 / 10 && pop < -8)) return 0;
rev = rev * 10 + pop;
}
return rev;
}
此算法判断溢出考虑到:MAX_VALUE : 2147483647 MIN_VALUE : -2147483648 。要判断最后一位不要大于 7 和 不要小于-8。
另一种简便算法,利用long类型做运算,先反转,最后判断溢出。
int reverse(int x)
{
int max = 0x7fffffff, min = 0x80000000;//int的最大值最小值
long rs = 0;//用long类型判断溢出
for(;x;rs = rs*10+x%10,x/=10);//逆序,正负通吃,不用单独考虑负值
return rs>max||rs<min?0:rs;//超了最大值低于最小值就返回0
}