7. 整数反转【每日一题】

题目:
给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [-231, 231 - 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。

示例1:

输入:x = 123
输出:321

示例 2:

输入:x = -123
输出:-321

示例 3:

输入:x = 120
输出:21

示例 4:

输入:x = 0
输出:0

提示:

  • -231 <= x <= 231 - 1

思路一:拿到这道题目,不考虑其数学特性的话,我们将一整串数字直接转换为字符串,然后翻转整个字符串,再考虑边界条件,将字符串转换为 int 64 位,如果溢出 int 32 则返回零。

class Solution {
    public int reverse(int x) {
        int sign = 1;
        String str = String.valueOf(x);
        if (x < 0)  {
            sign = -1;
            str = str.substring(1);
        }
        int len = str.length();
        char[] reversedChar = str.toCharArray();
        for (int i=0; i<len/2; i++) {
            reversedChar[i] = str.charAt(len-1-i);
            reversedChar[len-1-i] = str.charAt(i);
        }
        String reversedStr = new String(reversedChar);
        long reversedLong = Long.valueOf(reversedStr).longValue() * sign;
        if (reversedLong > (long) Integer.MAX_VALUE 
            || reversedLong < (long) Integer.MIN_VALUE) {
                return 0;
        }
        return Integer.valueOf(reversedStr) * sign;
    }
}

整个代码涉及到的边界处理有些麻烦,首先是负数转换为字符串的符号问题,需要通过 sign 保存和恢复相应的正负号;其次在翻转负数字符串时需要去掉第一位符号位。其次是溢出的问题,需要转换为 long 长整型来进行判断。

时间复杂度:O(n) 转换字符串 + O(n) 处理符号 + O(n/2) 翻转字符串 + O(n) 长整型转换 + O(n) 整型转换
空间复杂度:O(n) 额外的 char 数组

思路二:上述思路一的时间空间复杂度有点惨不忍睹,所以我们还是要考虑整型数字的数学特性,那么如何翻转一个整数呢?我们想到不断地取数字串的位数基本公式是 digit = x % 10, x = x / 10,同时构建出这个反序数字串其实也很简单:reversedx = 0, reversedx = reversedx * 10 + digit。整个解题思路也就相应变得很明确:

class Solution {
    public int reverse(int x) {
        long reversedx = 0;
        while(x != 0) {
            reversedx = reversedx * 10 + x % 10;
            x = x / 10;
        }
        return (int) reversedx == reversedx? (int)reversedx:0;
    }
}

让我们再看一下复杂度,
时间复杂度:仅有一个 while 循环,为 O(n)
空间复杂度:仅仅需要一个长整型不断记录翻转后的数值,所以为 O(1)

思路三:当然上述解题还是借用了 long 长整型进行溢出的判断,更进一步,是否能够不借助其他类型,仅仅用整型进行判断呢?其实是可以的。当数字串 x>0 的时候,溢出意味着 reversedx * 10 + x % 10 > Integer.MAX_VALUE,等式变换后相当于 reversedx > (Integer.MAX_VALUE - x % 10) / 10。同理,当数字串 x<0 的时候,溢出意味着 reversedx * 10 + x % 10 < Integer.MIN_VALUE, 等式变换后为 reversedx < (Integer.MIN_VALUE - x % 10) / 10。实现后的代码如下:

class Solution {
    public int reverse(int x) {
        int reversedx = 0;
        while(x!=0) {
            reversedx = reversedx * 10 + x % 10;
            x = x / 10;
            if (x > 0 && reversedx > (Integer.MAX_VALUE - x % 10) / 10) {
                return 0;
            }
            if (x < 0 && reversedx < (Integer.MIN_VALUE - x % 10) / 10) {
                return 0;
            }
        }
        return reversedx;
    }
}

虽然思路一的代码实现的不尽人意,这里有几个 java 语言点仍旧值得注意:

字符串与数字的相互转换

数字转为字符串

  • String的 ValueOf() 方法:
    这是最常用的方法,对于包装类以及基本数据类型都适用。
Integer x = 123;
String str1 = String.valueOf(x);
  • 直接拼接空字符串
String st2 = x + "";
  • 包装类的 toString() 方法
    注意该方法只适用于包装类,基本数据类型需要先调用包装类的 ValueOf() 方法再使用。
String str3 = x.toString();

字符串转数字

  • 使用包装类的 ValueOf() 方法
    通过包装类的 ValueOf() 方法,可以将字符串转换为想要的包装类,Byte、Short、Integer、Long、Float、Double 都有对应的 ValueOf() 方法。
Integer int1 = Integer.valueOf(str);
Double dou1 = Double.valueOf(str);
  • 使用包装类的 parseXXX() 方法
    通过包装类的 parseXXX() 方法,可以将字符串转换为想要的基本数据类型,同上都有相应的 parseXXX() 方法
int int2 = Integer.parseInt(str);
double dou2 = Double.parseDouble(str);

长整型同样囊括在上述方法之中

long long1 = Long.parseLong(str);
long long2 = Long.valueOf(str).longValue();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值