23

整数反转(ReverseInteger)

 4 years ago
source link: https://aquan.run/archives/整数反转(ReverseInteger)
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

bUFdIgKcN51C6s9.png

今天我来写一下 整数反转 的这一题,我们先目标把 简单难度 的题给刷了

题目地址: https://leetcode-cn.com/problems/reverse-integer/

题目描述

给出一个 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

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

自解

当时看到题目后,第一先想法就是 intString 后再转 char[] 数组后循环颠倒它的位置,后再转为 int 返回,最后自己欠缺考虑 =。= 没有考虑边缘值,和溢出的问题,最后用自己的方法没有通过,这样提醒我以后写代码时候要考虑和注意边缘值还有数据溢出的问题。 下面会有正确解法,还是自己的经验不够会这样想着解题。

没有成功:边缘值无法通过测试 -2147483648

自己当时的解题思路:

  • 第一步直接判断排除溢出的 -2147483648 治标不治本(这样写代码妈见打)
  • 在判断一下正负数,用flag记录下后面返回输出时候用到
  • 获取 X 的绝对值,转换为 String
  • String 再转换为 char[] 进行循环翻转拼接
  • 最后利用 BigDecimal 转换为 int ,根据 flag 转化为应该的正负数输出(为什么要用 BigDecimal 呢,因为别的包装类都会溢出.....)
  • 唔好学我鸭!

上代码

// 边缘值无法通过测试 -2147483648
public static int reverse(int x) {
    if (String.valueOf(x).equals("-2147483648")) {
        return 0;
    }
    Boolean flag = x>=0 ? true:false;
    String a = String.valueOf(Math.abs(x));
    String temp = "";
    char[] chars = a.toCharArray();
    for (int i=0; i<chars.length; i++) {
        temp = chars[i] + temp;
    }
    BigDecimal l = new BigDecimal(temp.trim());
    log.warn(String.valueOf(l));
    if (flag) {
        int result = l.intValue();
        if (String.valueOf(result).equals(String.valueOf(l))) {
            return l.intValue();
        } else {
            return 0;
        }
    } else {
        int result =  l.intValue();
        if (String.valueOf(result).equals(String.valueOf(l))) {
            return result * -1;
        } else {
            return 0;
        }
    }
}

正解

后面看了 官方的题解 后,是需要考虑是否溢出。

注意点:

  1. 如果 temp = rev * 10 + pop 导致溢出,那么一定会有 rev >= (Integer.MAX_VALUE / 10)
  2. 如果 rev > (Integer.MAX_VALUE / 10) ,那么 temp = rev * 10 + pop 一定会溢出
  3. 如果 rev == (Integer.MAX_VALUE / 10) ,那么只要 pop > 7,temp = rev * 10 + pop 就会溢出

理解思路:

  • 先要理解 Integer 的溢出,大于 Integer.MAX_VALUE 或者小于 Integer.MIN_VALUE 就会报错
  • 下面首先把 x 判断是否为 0 ,不是就先进行 % 余操作得到 pop
  • x 为什么要 x /= 10 就是 x = x / 10 这里就是要进行翻转的关键了,看一下下面的一段代码 栗子
// 假设我们输入的是12345,第一个循环
int rev = 0; //用来存储最后的结果
int x = 12345;
int pop = 12345 % 10; // pop = 5 (获取到了个位数)
x /= 10; // (12345 / 10) = 1234 (int没有小数自动取整)
rev = rev * 10 + pop; // 0 * 10 + 5 = 5 (rev的值为5)

// 第二个循环 (x=1234,rev=5)
int pop = x % 10; // pop = 4
x /= 10; // (1234 / 10) = 123
rev = rev * 10 + pop; // 5 * 10 + 4 = 54 (rev的值为54)
// 没错这里已经翻转了2个数了后面的也是同理
.....
  • 正负数都一样的

代码:

public static int reverseTwo(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;
}

总结

这就是这次的整数翻转了,希望大家不要学我开始的思路解法,写代码时候大家得考虑 溢出 的问题哦。

vQ367bF.png!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK