数位反转

题目描述:
编写一个Reverse函数,声明类似unsigned Reverse(unsigned);
要求参数只有一个32bit非负整数,
同样返回一个32bit整数,但数位反转。

输入:
按参数传递,一个32bit非负数,且最高最低位不为0

输出:
按返回值输出

样例输入:
2
19
120345

样例输出:
2
91
543021

其它:
请不要写上main函数

 

  1. #include<stdio.h>
  2. unsigned Reverse(unsigned a)
  3. {
  4.     unsigned i,j;
  5.     j=0;
  6.     while(a != 0){
  7.        i=a%10;
  8.        j=j*10+i;
  9.        a=a/10;
  10.       }
  11.     return j;
  12. }
<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type=text/javascript> </script>
<think>好的,我现在需要解决蓝桥杯竞赛中的数位反转问题。首先,我得明确题目要求。数位反转通常指的是将一个整数的各个数字顺序颠倒,比如将12345反转成54321。但可能题目会有额外的条件,比如处理前导零或者处理溢出的情况。根据引用[3],当反转后的数超过32位整数范围时需要进行判断,比如前九位已经超过214748364的话,无论最后一位是什么都会溢出。这一点需要注意。 首先,我得考虑如何反转数字。常规的方法是将数字逐位取模,然后累加到新数字上。例如,对于数字n,循环取n%10得到最后一位,然后加到反转后的数上,同时n = n // 10,直到n为0。这个过程需要注意正负号的问题,但通常题目可能只考虑正整数的情况,或者需要处理符号。假设题目中的数可能是负数,那么反转后的符号是否保留?比如-123反转成-321。需要根据题目具体要求来处理。 然后,处理溢出问题。32位有符号整数的范围是-2^31到2^31-1,即-2147483648到2147483647。反转后的数如果超出这个范围,应该返回0或者其他特定值。根据引用[3]的方法,可以在反转过程中每一步检查是否溢出。比如,当反转数rev大于214748364时,或者等于214748364但下一位数字大于7(因为最大值2147483647的最后一位是7),那么无论后面如何都会溢出。同样,负数的情况,如果rev小于-214748364,或者等于-214748364但下一位小于-8,就溢出。这样可以在反转过程中提前终止,避免处理全部位数。 接下来,我需要考虑示例代码的结构。可以使用循环来处理每一位数字,同时每一步检查溢出。例如,初始化rev为0,然后循环取出原数的最后一位,加到rev上,同时原数去掉最后一位。在每次循环时判断当前rev是否已经超出范围,或者是否可能在下一步溢出。 例如,假设输入是n=1234567899,反转后的正确结果应该是9987654321,这超过了2147483647,所以应该返回0。在反转过程中,当处理到前九位时,rev是987654321,此时如果还有下一位要处理(比如原数还有更多的位数),那么加上下一位可能会导致溢出,所以需要提前判断。或者当处理到第九位时,rev已经是98765432,下一步加上第九位(比如9)变成987654329,此时可能已经超过最大值的前九位部分,从而溢出。 可能的步骤: 1. 处理符号,记录符号,将n转为正数处理。 2. 反转数字,每次取余得到最后一位,加到rev。 3. 在每一步反转时检查是否可能溢出: - 对于正数,如果rev > 214748364,或者rev等于214748364且下一位数字>7,则溢出。 - 对于负数,如果rev < -214748364,或者等于-214748364且下一位数字<-8,则溢出。 4. 处理前导零的问题,比如输入是100,反转后应该是1,而不是001,但通过数字处理的话,反转后的数自动省略前导零,所以不需要额外处理。 然后,编写代码的时候需要考虑这些情况。例如,在Python中,整数没有溢出问题,但题目可能要求模拟32位有符号整数的情况,所以必须手动判断溢出。 示例代码的大致结构: def reverse_num(n): rev = 0 sign = 1 if n < 0: sign = -1 n = -n while n > 0: digit = n % 10 # 检查正数溢出 if sign == 1: if rev > 214748364 or (rev == 214748364 and digit > 7): return 0 # 检查负数溢出 else: if rev > 214748364 or (rev == 214748364 and digit > 8): return 0 rev = rev * 10 + digit n = n // 10 rev *= sign # 最终检查是否超出范围 if rev > 2147483647 or rev < -2147483648: return 0 return rev 不过这里可能有问题,比如在循环中的判断是否应该放在乘以sign之前。或者在处理负数的时候,是否应该在反转过程中检查不同的条件。例如,对于负数,当rev在反转过程中不考虑符号的话,可能判断条件不同。或者是否应该在处理过程中将符号分开处理。 可能正确的处理方式是,在反转过程中不考虑符号,将n转为正数处理,反转结束后应用符号。在反转过程中,检查的是不带符号的数值是否超过INT_MAX的绝对值。例如,对于INT_MAX是2147483647,当处理不带符号的rev时,如果超过这个值,则溢出。但在反转过程中,每次处理时,如果rev在乘以10并加上digit后会超过INT_MAX,则提前返回0。 另一种方法是,在反转过程中,每次计算新的rev前,检查是否会导致溢出。例如,在Python中: INT_MAX = 2**31 -1 INT_MIN = -2**31 def reverse(x): rev = 0 sign = 1 if x >=0 else -1 x = abs(x) while x !=0: digit = x %10 x = x //10 # 检查是否溢出 if rev > (INT_MAX //10) or (rev == INT_MAX//10 and digit > INT_MAX %10): return 0 rev = rev *10 + digit return rev * sign 这里,INT_MAX//10是214748364,余数是7。所以当rev超过这个值,或者等于这个值且digit超过7,则溢出。对于负数的情况,因为处理的是绝对值,所以当反转后的绝对值超过INT_MAX的话,乘以符号后可能会小于INT_MIN吗?例如,如果rev是2147483648,乘以-1的话就是-2147483648,这正好是INT_MIN,所以可能在代码中需要额外处理这种情况。例如,原数反转后的绝对值是2147483648,那么如果是负数,结果就是-2147483648,这在32位整数中是允许的。因此,可能需要调整判断条件。 例如,在反转过程中,当处理绝对值时,如果rev超过INT_MAX//10,或者在等于的情况下digit超过7(对于正数),或者digit超过8(对于负数的情况),因为INT_MIN的绝对值最后一位是8。比如,原数是-8463847412,反转后的绝对值是2147483648,此时符号为负,结果为-2147483648,刚好是INT_MIN,所以应该允许。因此,原来的判断条件可能不够准确。 所以,正确的判断应该根据符号来处理。例如,如果是正数,则反转后的数不能超过INT_MAX。如果是负数,则反转后的数不能小于INT_MIN。因此,在反转过程中,可能需要分开处理符号的情况。例如,在反转绝对值的时候,如果符号为正,那么rev必须<=INT_MAX;如果符号为负,则rev必须<=INT_MAX +1(因为INT_MIN的绝对值是INT_MAX +1)。例如: def reverse(x): rev = 0 sign = 1 if x >=0 else -1 x_abs = abs(x) max_limit = (2**31 -1) //10 if sign ==1 else (2**31) //10 while x_abs >0: digit = x_abs %10 x_abs = x_abs //10 if rev > max_limit or (rev == max_limit and digit > (7 if sign ==1 else8)): return 0 rev = rev *10 + digit return rev * sign 这样,当符号为正时,最大允许的rev在乘以10前是214748364(即INT_MAX//10=214748364),digit不能超过7(因为INT_MAX的最后一位是7);当符号为负时,最大允许的rev在乘以10前是214748364(因为INT_MIN//10是-214748364,其绝对值是214748364,digit不能超过8,因为INT_MIN的最后一位是8)。 这可能更准确。例如,当处理负数时,如果反转后的绝对值是2147483648,那么乘以符号得到-2147483648,刚好是INT_MIN,是有效的,应该返回这个结果而不是溢出。而原来的代码可能无法处理这种情况,因为之前的判断可能错误地将其视为溢出。 因此,正确的条件应该是: 如果是正数: - 在每一步,如果rev > INT_MAX//10 → 溢出 - 或者 rev == INT_MAX//10且digit > 7 → 溢出 如果是负数: - 在每一步,如果rev > (INT_MAX +1)//10 → 溢出(因为INT_MIN的绝对值是2147483648,所以INT_MAX+1是2147483648,其除以10是214748364.8,所以整数除法为214748364。因此,当rev >214748364,或者rev等于它且digit>8,则溢出。) 因此,修改代码中的条件: max_limit = (2**31 -1) //10 if sign ==1 else (2**31)//10 digit_limit = 7 if sign ==1 else8 所以在循环中: digit = x_abs %10 if rev > max_limit or (rev == max_limit and digit > digit_limit): return 0 这样处理的话,当符号为负时,允许digit最多到8,这样当原数是-8463847412,反转后的绝对值是2147483648,此时rev在每一步的处理中: 假设原数x_abs是8463847412,反转后的数字应该是2147483648,这在符号为负的情况下是允许的。在反转过程中: 每一步的处理: 初始rev=0,digit=2 → rev=2 → 检查是否超过max_limit(对于负号,max_limit是214748364(因为2^31//10=2147483648//10=214748364))。此时rev=2 ≤ max_limit,继续。 接下来x_abs=846384741,digit=1 → rev=21 → 检查:21 < 214748364 → 继续。 继续处理直到rev=214748364,digit=8 → 检查rev == max_limit(214748364),digit=8是否超过digit_limit=8?等于的情况下是否允许?如果条件为digit>digit_limit的话,当digit是8时,等于digit_limit,所以允许。那么rev=214748364 *10 +8=2147483648 → 此时乘以符号-1得到-2147483648,这是正确的。因此,条件应该是digit > digit_limit时才返回溢出。所以当digit等于8时,允许,不会溢出。 所以,条件中的比较应该是digit > digit_limit,而digit_limit在负号情况下是8,因此当digit等于8时,条件不成立,不会返回0。这样就能正确处理这种情况。 因此,正确的代码应该像这样: def reverse(x): INT_MAX = 2**31 -1 INT_MIN = -2**31 rev =0 sign =1 if x>=0 else -1 x_abs = abs(x) max_limit = INT_MAX //10 if sign ==1 else (INT_MIN // -10) digit_limit = INT_MAX %10 if sign ==1 else -(INT_MIN %10) while x_abs >0: digit = x_abs %10 x_abs =x_abs//10 if rev > max_limit or (rev == max_limit and digit > digit_limit): return 0 rev = rev *10 + digit return rev * sign 这里,对于符号为负的情况,max_limit是INT_MIN // -10。例如,INT_MIN是-2147483648,除以-10得到214748364.8,整数除法得到214748364。digit_limit是 -(INT_MIN%10):因为INT_MIN%10是-8(在Python中,负数取模的结果符号由除数决定),所以INT_MIN%10是-8,取反得到8。这样digit_limit在符号为负时是8。 这样处理的话,就能正确判断是否溢出。例如,当x=-8463847412时,反转后的绝对值是2147483648,此时在最后一步digit=8: rev在进入这一步之前是214748364,此时digit=8。max_limit是214748364,digit_limit是8。条件rev == max_limit且digit >8?不成立,所以允许。rev变为214748364*10 +8=2147483648,乘以符号得到-2147483648,在INT_MIN的范围内,所以正确返回该值。 所以这段代码能够正确处理这种情况。 总结步骤: 1. 确定符号,将数转为绝对值处理。 2. 设置max_limit和digit_limit,根据符号不同而不同。 3. 在循环中取出每一位digit,并更新rev。 4. 在每次更新前检查是否会导致溢出。 5. 最后返回带符号的结果。 现在需要将这个思路转化为中文的回答,并提供示例代码。同时,根据用户的问题,用户希望寻找蓝桥杯竞赛中的数位反转问题的解法或示例代码,所以需要结合引用中的信息,特别是引用[3]提到的溢出判断方法。 可能的示例代码如下(Python): def reverse_number(x): INT_MAX = 2**31 - 1 INT_MIN = -2**31 rev = 0 sign = 1 if x >= 0 else -1 x_abs = abs(x) max_limit = INT_MAX // 10 if sign == 1 else (INT_MIN // -10) digit_limit = INT_MAX % 10 if sign == 1 else -(INT_MIN % 10) while x_abs > 0: digit = x_abs % 10 x_abs = x_abs // 10 if rev > max_limit or (rev == max_limit and digit > digit_limit): return 0 rev = rev * 10 + digit return sign * rev 这个函数处理了32位整数反转,并在溢出时返回0。例如: 输入:123 → 输出:321 输入:-123 → 输出:-321 输入:2147483647 → 输出:7463847412 → 超过INT_MAX,返回0。 输入:-8463847412 → 输出:-2147483648(即INT_MIN),因为反转后的绝对值2147483648在乘以符号后等于INT_MIN,所以是有效的。 根据引用[3]中的判断方法,当反转的前九位超过214748364时,直接返回溢出。这里的条件判断在每一步进行,提前终止处理,符合该思路。 因此,这个代码应该能正确解决问题。</think>### 数位反转问题解法 数位反转的核心是将整数每一位数字逆序重组,并确保结果在32位有符号整数范围内($-2^{31} \leq x \leq 2^{31}-1$)。以下是具体实现步骤: 1. **符号处理** 记录原始数字的符号,将数值转为正数处理,反转后再恢复符号。 2. **逐位反转** 通过取模运算逐位提取数字,构建反转后的数值。例如: 原数 $n=123$,逐次提取 $3$, $2$, $1$,组合为 $321$。 3. **溢出判断** 反转过程中需实时检查是否超出32位整数范围: - **正数**:若当前结果 $rev > 214748364$,或 $rev = 214748364$ 且下一位 $digit > 7$,则溢出。 - **负数**:若当前结果 $rev > 214748364$,或 $rev = 214748364$ 且下一位 $digit > 8$,则溢出[^3]。 **示例代码(Python):** ```python def reverse_number(x): INT_MAX = 2**31 - 1 INT_MIN = -2**31 rev = 0 sign = 1 if x >= 0 else -1 x_abs = abs(x) max_limit = INT_MAX // 10 if sign == 1 else (INT_MIN // -10) digit_limit = INT_MAX % 10 if sign == 1 else -(INT_MIN % 10) while x_abs > 0: digit = x_abs % 10 x_abs = x_abs // 10 if rev > max_limit or (rev == max_limit and digit > digit_limit): return 0 rev = rev * 10 + digit return sign * rev ``` **示例分析:** - 输入:`123` → 反转后为 `321`,未溢出,直接返回。 - 输入:`2147483647` → 反转后为 `7463847412`,超过 $2^{31}-1$,返回 `0`。 - 输入:`-8463847412` → 反转后绝对值为 `2147483648`,符号为负,结果为 `-2147483648`(即 $INT\_MIN$),属于合法范围[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值