7.整数反转Java

该博客介绍了如何在Java中反转一个32位有符号整数,包括可能的溢出检查和两种解决方案:直接操作数字避免溢出和转换为字符串进行反转。提供了具体的输入输出示例,并分析了算法的时间复杂度和空间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

7.整数反转Java

题目描述

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

输入输出样式

示例1:
输入:x = 123
输出:321

示例2:
输入:x = -123
输出:-321

本题来自LeetCode:https://leetcode-cn.com/problems/reverse-integer/

思路

方法一:每次取输入数字的末尾一个数,依次实现反转。但是要注意溢出问题,因为这里允许32位不能用64位存储的long型。
在这里插入图片描述

方法二:利用字符串,将数字转化为字符串,调用字符串reverse方法。同时注意溢出和符号问题。

算法分析

时间复杂度O(log |x|),空间复杂度为O(1)

求解函数

public int reverse(int x) {
        int rev = 0;
        while (x != 0) {
       		//溢出则直接返回0
            if (rev < Integer.MIN_VALUE / 10 || rev > Integer.MAX_VALUE / 10) {
                return 0;
            }
            int digit = x % 10;
            x /= 10;
            rev = rev * 10 + digit;
        }
        return rev;
    }
    public int reverse(int x) {
        // 判断符号,存起来
        int op = x>0?1:-1;
        x = Math.abs(x);
        String s = new StringBuffer(String.valueOf(x)).reverse().toString();
        String sMax = String.valueOf(Integer.MAX_VALUE);
        int length = sMax.length();
        //判断溢出
        if(s.length()>=length && s.compareTo(sMax)>0){
            return 0;
        }
        return Integer.valueOf(s) *op;
    }
<think>嗯,用户让我介绍一下整数反转Java中的实现方法。首先,我得回想一下整数反转的常见方法。通常,这涉及到逐位取出原数字的各位数,然后反向组合成新数字。不过要注意处理溢出问题,因为Java的int类型有范围限制,-2^31到2^31-1。 首先,我应该考虑如何处理负数的情况。可能的方法是将负数转为正数处理,或者直接处理符号位。比如,可以先判断数字是否为负,记录符号,然后处理绝对值部分,最后再恢复符号。这样可以简化计算。 然后,关键的步骤是反转数字。比如,原数字是123,反转后是321。这可以通过循环取余和除法来实现。每次循环中,取出最后一位(通过num % 10),然后添加到反转后的数字中。同时,原数字不断除以10去掉最后一位。 不过,这里有个问题,反转后的数字可能会超过int的范围。比如,反转后的结果超过Integer.MAX_VALUE或小于Integer.MIN_VALUE时,应该返回0。那怎么检测溢出呢?在Java中,可能需要在每次乘以10之前检查是否会溢出。比如,当反转的结果rev已经大于Integer.MAX_VALUE/10,那么乘以10之后肯定会溢出。或者等于Integer.MAX_VALUE/10时,余数是否超过7(因为Integer.MAX_VALUE的最后一位是7)。 举个例子,假设输入是1463847412,反转后是2147483641,这在int范围内。但如果输入是1534236469,反转后是9646324351,这超过了int的最大值,应该返回0。 那具体的步骤应该是这样的:初始化反转后的数字rev为0。循环处理原数字,每次取最后一位pop。然后,rev = rev * 10 + pop。但在每次这一步之前,需要检查rev是否在乘以10后是否会溢出。比如,如果rev > Integer.MAX_VALUE/10,或者rev等于Integer.MAX_VALUE/10且pop>7,那么就会溢出。负数的情况类似,如果rev < Integer.MIN_VALUE/10,或者等于的话且pop<-8,就会溢出。 这时候,需要把这些条件写在循环中,每次迭代的时候检查。如果溢出,直接返回0。 另外,原数字在每次处理后要除以10,直到变成0为止。 现在,将这些步骤转化为Java代码。例如: 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; } 这样处理应该可以覆盖所有情况。需要注意Java中的除法对于负数的处理,比如-123 % 10得到的是-3,这样在循环中pop的值会是负数,但后续的rev计算会自动处理符号,因为每次迭代都会带符号相加。例如,原数是-123,第一次pop是-3,x变成-12。rev初始是0,所以rev=0*10 + (-3) = -3。下一次pop是-2,x变成-1。rev变成-3*10 + (-2) = -32。最后pop是-1,x变成0。rev变成-32*10 + (-1) = -321,这样就正确反转了。 但是,在代码中,是否需要对负数进行特殊处理?比如,将x转为正数处理?可能不需要,因为上述代码已经处理了负数的情况。因为当x为负数时,x%10会得到负数,而x/=10也会正确地向零取整。例如,-123 /10 在Java中是-12,而不是-13,因为Java的除法是向零取整的。所以循环可以正确处理负数的情况。 测试几个例子:比如输入是123,反转得到321。输入是-123,得到-321。输入是120,得到21。输入是0,返回0。输入是1534236469,反转后应为0,因为反转后的值超过Integer.MAX_VALUE(2147483647)。 那么这样的代码应该可以正确工作。但需要注意边界情况,比如输入是-2147483648(即Integer.MIN_VALUE),反转后的数值应该是-8463847412,这显然超出了int的范围,所以应该返回0。在代码中,当处理到最后一个数字8的时候,rev此时是-846384741,当尝试乘以10并加上8的时候,需要检查是否溢出。此时,rev是-846384741,而Integer.MIN_VALUE是-2147483648。Integer.MIN_VALUE /10 是-214748364。所以比较rev是否小于这个值:-846384741 < -214748364,显然成立,所以进入溢出条件,返回0。因此,这个情况会被正确处理。 总结一下,这个算法的步骤是: 1. 初始化rev为0。 2. 循环处理x的每一位,直到x为0: a. 取出最后一位pop = x % 10。 b. x = x / 10。 c. 检查rev乘以10加上pop是否会导致溢出。如果是,返回0。 d. 更新rev = rev * 10 + pop。 3. 返回rev。 这样处理可以确保反转后的数在int范围内,否则返回0。这个算法的时间复杂度是O(log(x)),因为x的位数大约是log10(x)次循环。空间复杂度是O(1)。 可能还有其他的实现方式,比如先将数字转为字符串反转后再转回来,但这样需要处理前导零和溢出,可能效率更低,且需要处理异常。而上述方法更高效,直接通过数学运算处理,避免了字符串转换的开销。 用户可能需要了解不同的实现方式,但上述方法是最优解。另外,需要提醒用户注意处理溢出,这是整数反转问题中的关键点。</think>### 整数反转Java实现详解 **问题描述** 给定一个32位有符号整数`x`,将其数字部分反转,若反转后超出整数范围($-2^{31} \leq x \leq 2^{31}-1$),返回0。 --- #### **步骤解析** 1. **初始化反转结果** 定义变量`rev`存储反转结果,初始值为0。 2. **循环处理每一位数字** 只要原数字`x`不为0,重复以下步骤: - **取出末位数字**:`pop = x % 10` - **去掉末位**:`x = x / 10` 3. **溢出检测** 在更新`rev`前,检查是否溢出: - 若`rev > Integer.MAX_VALUE / 10`,或`rev == Integer.MAX_VALUE / 10`且`pop > 7` → **正溢出** - 若`rev < Integer.MIN_VALUE / 10`,或`rev == Integer.MIN_VALUE / 10`且`pop < -8` → **负溢出** 4. **更新反转结果** 若未溢出,执行`rev = rev * 10 + pop` --- #### **Java代码实现** ```java 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; } ``` --- #### **关键点解析** 1. **负数处理** 利用Java的取余特性(负数取余结果仍为负),无需额外处理符号,例如: - 输入`-123` → `pop`依次为`-3`, `-2`, `-1` → 反转后为`-321` 2. **溢出检测逻辑** - `Integer.MAX_VALUE = 2147483647` → 末位为7,若`rev == 214748364`且`pop > 7`,则`rev * 10 + pop`超过上限。 - `Integer.MIN_VALUE = -2147483648` → 末位为-8,若`rev == -214748364`且`pop < -8`,则超出下限。 3. **复杂度分析** - **时间复杂度**:$O(\log |x|)$,数字位数约为$\log_{10} |x|$。 - **空间复杂度**:$O(1)$,仅用常数级额外空间。 --- #### **示例测试** | 输入 | 输出 | 解释 | |------------|----------|------------------------------| | `123` | `321` | 正常反转 | | `-123` | `-321` | 负数反转 | | `120` | `21` | 去除前导零 | | `1534236469` | `0` | 反转后超过`Integer.MAX_VALUE` | --- #### **其他实现对比** - **字符串反转法** 将数字转为字符串反转后转回整数。需处理前导零和溢出异常,效率较低。 - **数学运算法(推荐)** 直接通过取余和除法操作,无需类型转换,效率更高。 --- 通过以上步骤,可以高效且安全地实现整数反转功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值