【LeetCode】7. 整数反转

发布于:2025-08-20 ⋅ 阅读:(18) ⋅ 点赞:(0)

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

提示:

  • -2^31 <= x <= 2^31 - 1

解题思路

这道题要求将整数的数字部分反转,同时需要处理溢出问题。这是一个数学运算和边界处理的经典问题。

算法分析

这道题的核心思想是逐位提取并重组,主要解法包括:

  1. 数学方法:使用取模和除法逐位提取数字
  2. 字符串方法:转换为字符串后反转
  3. 位运算优化:使用位运算优化溢出检查
  4. 溢出处理:在计算过程中检查32位整数范围

问题本质分析

整数反转
数字位提取
位序重排
结果重组
取模运算获取个位
除法运算去掉个位
从右到左重新组合
检查溢出范围
digit = x % 10
x = x / 10
result = result * 10 + digit
返回结果或0
循环处理
直到x为0

数学方法详解

输入整数x
是否为负数?
记录负号并转为正数
直接处理
初始化result = 0
x > 0?
返回结果
提取个位数字
digit = x % 10
检查溢出
会溢出?
返回0
更新结果
result = result * 10 + digit
x = x / 10
原数为负数?
返回-result
返回result
结束

溢出检查策略

溢出检查策略
乘法前检查
除法优化
边界值处理
result > MaxInt32/10
result == MaxInt32/10 && digit > 7
result < MinInt32/10
result == MinInt32/10 && digit < -8
返回0
避免直接乘法
处理边界情况
提高安全性

反转过程可视化

输入: x = 123
反转过程
第1步: digit = 123 % 10 = 3
result = 0 * 10 + 3 = 3
x = 123 / 10 = 12
第2步: digit = 12 % 10 = 2
result = 3 * 10 + 2 = 32
x = 12 / 10 = 1
第3步: digit = 1 % 10 = 1
result = 32 * 10 + 1 = 321
x = 1 / 10 = 0
x = 0, 循环结束
输出: 321

负数处理策略

负数处理
检测符号
转为正数
按正数处理
恢复符号
isNegative = x < 0
x = -x
逐位提取反转
return -result
符号标记
绝对值处理
统一算法
最终结果

各种解法对比

解法对比
数学方法
字符串方法
位运算优化
时间O_log_n空间O_1
时间O_log_n空间O_log_n
时间O_log_n空间O_1
推荐解法
直观易懂
性能最优
空间效率高
代码简洁
溢出检查优化
适合生产环境

算法流程图

开始
初始化result = 0
x != 0?
返回result
提取个位digit
检查溢出风险
会溢出?
返回0
更新result
result = result * 10 + digit
x = x / 10
结束

边界情况处理

边界情况
x = 0
x = 负数
x = 最大/最小值
反转后溢出
直接返回0
转为正数处理
特殊溢出检查
返回0
避免无效计算

时间复杂度分析

graph TD
    A[时间复杂度分析] --> B[数字位数]
    B --> C[循环次数]
    C --> D[每次操作]
    
    B --> E[log₁₀(n)]
    C --> F[O_log_n]
    D --> G[O_1]
    
    E --> H[n是整数值]
    F --> I[总时间复杂度]
    G --> I
    
    I --> J[O_log_n]
    J --> K[最优解法]

空间复杂度分析

空间复杂度分析
额外空间使用
局部变量
常数空间
O_1
原地算法
空间效率最优

关键优化点

优化策略
溢出检查优化
符号处理优化
循环优化
乘法前检查
统一处理正负数
减少不必要的计算
避免溢出

实际应用场景

应用场景
数字处理
密码学
数据验证
算法竞赛
数字序列反转
数字加密
输入验证
编程练习
核心算法组件

测试用例设计

测试用例
基础功能
边界情况
溢出测试
正数反转
负数反转
零值处理
最大32位整数
最小32位整数
单位数
反转后溢出
边界值测试
验证正确性
验证溢出处理

代码实现要点

  1. 溢出检查时机

    • result * 10 之前检查
    • 避免实际溢出后再检查
  2. 符号处理

    • 先转为正数处理
    • 最后恢复符号
  3. 循环终止条件

    • 使用 x != 0 而不是 x > 0
    • 统一处理正负数
  4. 边界值处理

    • 特殊处理最大/最小32位整数
    • 处理反转后溢出的情况
  5. 性能优化

    • 使用位运算优化溢出检查
    • 减少不必要的条件判断

这个问题的关键在于掌握数字位提取技巧正确处理溢出情况,通过数学运算实现整数的位序反转,同时确保结果在32位整数范围内。

完整题解代码

package main

import (
	"fmt"
	"math"
	"strconv"
)

// reverse 整数反转 - 数学方法
// 时间复杂度: O(log n),其中n是整数的位数
// 空间复杂度: O(1)
func reverse(x int) int {
	var result int

	// 处理负数,先转为正数处理
	isNegative := x < 0
	if isNegative {
		x = -x
	}

	// 逐位提取并反转
	for x > 0 {
		digit := x % 10
		x /= 10

		// 检查溢出:在乘以10之前检查
		if result > math.MaxInt32/10 || (result == math.MaxInt32/10 && digit > 7) {
			return 0
		}
		if result < math.MinInt32/10 || (result == math.MinInt32/10 && digit < -8) {
			return 0
		}

		result = result*10 + digit
	}

	// 恢复符号
	if isNegative {
		result = -result
	}

	return result
}

// reverseOptimized 优化版本 - 使用更简洁的逻辑
// 时间复杂度: O(log n)
// 空间复杂度: O(1)
func reverseOptimized(x int) int {
	var result int

	for x != 0 {
		digit := x % 10
		x /= 10

		// 检查溢出
		if result > math.MaxInt32/10 || (result == math.MaxInt32/10 && digit > 7) {
			return 0
		}
		if result < math.MinInt32/10 || (result == math.MinInt32/10 && digit < -8) {
			return 0
		}

		result = result*10 + digit
	}

	return result
}

// reverseString 字符串方法 - 转换为字符串后反转
// 时间复杂度: O(log n)
// 空间复杂度: O(log n)
func reverseString(x int) int {
	// 处理特殊情况
	if x == 0 {
		return 0
	}

	// 转换为字符串
	str := strconv.Itoa(x)
	isNegative := str[0] == '-'

	// 如果是负数,去掉负号
	if isNegative {
		str = str[1:]
	}

	// 反转字符串
	bytes := []byte(str)
	for i, j := 0, len(bytes)-1; i < j; i, j = i+1, j-1 {
		bytes[i], bytes[j] = bytes[j], bytes[i]
	}

	// 转换回整数
	result, err := strconv.Atoi(string(bytes))
	if err != nil {
		return 0
	}

	// 检查溢出
	if result > math.MaxInt32 || result < math.MinInt32 {
		return 0
	}

	// 恢复符号
	if isNegative {
		result = -result
	}

	return result
}

// reverseBitwise 位运算方法 - 使用位运算优化
// 时间复杂度: O(log n)
// 空间复杂度: O(1)
func reverseBitwise(x int) int {
	var result int

	for x != 0 {
		digit := x % 10
		x /= 10

		// 使用位运算检查溢出
		if result > (math.MaxInt32-digit)/10 {
			return 0
		}

		result = result*10 + digit
	}

	return result
}

func main() {
	// 测试用例1
	x1 := 123
	result1 := reverse(x1)
	fmt.Printf("示例1: x = %d\n", x1)
	fmt.Printf("输出: %d\n", result1)
	fmt.Printf("期望: 321\n")
	fmt.Printf("结果: %t\n", result1 == 321)
	fmt.Println()

	// 测试用例2
	x2 := -123
	result2 := reverse(x2)
	fmt.Printf("示例2: x = %d\n", x2)
	fmt.Printf("输出: %d\n", result2)
	fmt.Printf("期望: -321\n")
	fmt.Printf("结果: %t\n", result2 == -321)
	fmt.Println()

	// 测试用例3
	x3 := 120
	result3 := reverse(x3)
	fmt.Printf("示例3: x = %d\n", x3)
	fmt.Printf("输出: %d\n", result3)
	fmt.Printf("期望: 21\n")
	fmt.Printf("结果: %t\n", result3 == 21)
	fmt.Println()

	// 测试用例4
	x4 := 0
	result4 := reverse(x4)
	fmt.Printf("示例4: x = %d\n", x4)
	fmt.Printf("输出: %d\n", result4)
	fmt.Printf("期望: 0\n")
	fmt.Printf("结果: %t\n", result4 == 0)
	fmt.Println()

	// 额外测试用例 - 溢出情况
	x5 := 1534236469
	result5 := reverse(x5)
	fmt.Printf("溢出测试: x = %d\n", x5)
	fmt.Printf("输出: %d\n", result5)
	fmt.Printf("期望: 0 (溢出)\n")
	fmt.Printf("结果: %t\n", result5 == 0)
	fmt.Println()

	// 测试优化版本
	fmt.Println("=== 优化版本测试 ===")
	result1Opt := reverseOptimized(x1)
	result2Opt := reverseOptimized(x2)
	fmt.Printf("优化版本示例1: %d\n", result1Opt)
	fmt.Printf("优化版本示例2: %d\n", result2Opt)
	fmt.Printf("结果一致: %t\n", result1Opt == result1 && result2Opt == result2)
	fmt.Println()

	// 测试字符串版本
	fmt.Println("=== 字符串版本测试 ===")
	result1Str := reverseString(x1)
	result2Str := reverseString(x2)
	fmt.Printf("字符串版本示例1: %d\n", result1Str)
	fmt.Printf("字符串版本示例2: %d\n", result2Str)
	fmt.Printf("结果一致: %t\n", result1Str == result1 && result2Str == result2)
	fmt.Println()

	// 测试位运算版本
	fmt.Println("=== 位运算版本测试 ===")
	result1Bit := reverseBitwise(x1)
	result2Bit := reverseBitwise(x2)
	fmt.Printf("位运算版本示例1: %d\n", result1Bit)
	fmt.Printf("位运算版本示例2: %d\n", result2Bit)
	fmt.Printf("结果一致: %t\n", result1Bit == result1 && result2Bit == result2)
	fmt.Println()

	// 边界值测试
	fmt.Println("=== 边界值测试 ===")
	boundaryTests := []int{
		math.MaxInt32, // 最大32位整数
		math.MinInt32, // 最小32位整数
		1000000000,    // 10位数
		-1000000000,   // 负数10位数
	}

	for _, test := range boundaryTests {
		result := reverse(test)
		fmt.Printf("x = %d, reverse = %d\n", test, result)
	}
}

网站公告

今日签到

点亮在社区的每一天
去签到