洛谷 P1307 [NOIP2011 普及组] 数字反转

本文介绍了如何根据给定的整数N,将其各位数字反转,确保新数符合整数格式且非零(除零本身外)。涉及输入判断、位数计算、数组存储以及处理负数的方法,提供了完整代码示例。

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

题目描述

给定一个整数 N,请将该数各个位上数字反转得到一个新数。新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零(参见样例 2)。

输入格式

一个整数 N。

输出格式

一个整数,表示反转后的新数。

输入输出样例

输入 #1

123

输出 #1

321

输入 #2

-380

输出 #2复制

-83

说明/提示

【数据范围】

−1,000,000,000 ≤ N ≤ 1,000,000,000。

noip2011 普及组第一题

解题思路

读懂题后就可以开始思考、写题了

第一部分

头文件+定义

a数组存储n各位上的数

n为输入的数,c用来判断末尾的0,i计算n有几位

第二部分

n=0和n>0的判断

13~18:通过while循环求出n一共有几位,并将每位上的数存进a数组

19~28:循环判断末尾上的数是否为0,是0就不输出,不是0就输出

第三部分

负数的判断方法与正数的基本一致,不过要先将n*-1变成正数,这样方便计算,最后在输出前多输出一个-就可以了

完整代码

<think>好的,我现在需要解决用户的问题,即如何用Python实现NOIP2011普及组题目P1307数字反转功能。首先,我要仔细理解题目要求。题目要求将输入的数字反转,同时要考虑前导零和负的情况。例如,输入-380输出-83,输入1200输出21,输入0则输出0。 根据用户提供的引用内容,特别是引用3和引用4中的Python代码示例,我需要分析不同的实现方法。用户提供的引用3中的代码使用了取余和循环的方法,逐处理数字。而引用4提到可能存在超时问题,所以需要考虑效率。此外,引用5提到使用字符组处理,可能涉及字符串反转的方法。 首先,我需要确定反转数字的步骤。对于负,可以先处理符号,反转绝对值部分。对于末尾的零,反转后需要去除。例如,输入-380,处理绝对值380,反转得到083,去除前导零得到83,再加上负号,结果-83。对于1200,反转后0021,去除前导零得到21。零的情况直接输出0。 接下来,考虑不同的实现方法。一种是学方法,逐取余和整除,如引用3中的代码。另一种是字符串处理,将数字转为字符串,反转后处理符号和前导零。这两种方法哪种更优? 学方法的步骤是:处理符号,反转数字。例如,对于n=123,循环取余得到3,然后n变为12,sum=3;下一步取余2,sum=3*10+2=32,n变为1;最后取余1,sum=32*10+1=321。处理负时,先取绝对值,反转后加符号。这种方法的时间复杂度是O(log n),因为循环次数字有关,对于大来说效率应该没问题,但引用4提到有代码超时,可能是实现方式的问题,比如循环中的某些操作效率低。 字符串方法更直观:将数字转为字符串,去掉符号后反转,处理前导零,最后加上符号。例如,n=-380转为字符串"380",反转"083",去除前导零得到"83",加上符号得到"-83"。这种方法在Python中可能更简洁,但需要注意处理零的情况,比如输入为0时,反转后还是0。 现在需要考虑两种方法的优缺点。学方法适用于大吗?Python的整处理能力很强,所以应该没问题。字符串方法在代码简洁性上有优势,但可能涉及类型转换,不过对于题目给定据范围(-1e9到1e9),两种方法应该都适用。 接下来,根据用户提供的引用3中的代码,分析其可能的不足。引用3的代码是: def rem(n): k = int(n/10) r = n - k*10 return r n = int(input()) sum = 0 while n != 0: sum = sum*10 + rem(n) n = int(n/10) print(sum) 这段代码在处理负时会出问题,因为当n为负时,int(n/10)在Python中是向下取整,会导致余可能为负。例如,n=-380时,第一次循环,rem(-380)计算r=-380 - (-38*10) = -380 + 380 = 0,sum=0*10 +0=0,n变为-38。第二次循环,rem(-38)得到-8,sum=0*10 + (-8) = -8,n变为-3。第三次循环,rem(-3)得到7(因为k=int(-3/10)=0,所以r=-3 -0= -3?这里可能有问题)。或者,原代码中的rem函可能有问题,因为Python中负取余的处理方式可能和预期不同。 例如,在Python中,-380 // 10是-38,所以k=-38,r=-380 - (-38)*10 = -380 +380=0。所以sum=0,n变为-38。第二次循环,n=-38,k=int(-38/10)=-3(因为-38/10=-3.8,int转换得到-3),所以r=-38 - (-3)*10 = -38 +30 = -8。sum=0*10 + (-8)=-8,n=-3。第三次循环,k=int(-3/10)=0,r=-3 -0*10=-3。sum=-8*10 + (-3)=-83,n=0。循环结束,输出-83。这似乎是正确的。但原代码在Python中处理负时,是否会出现问题?比如,当n为负时,循环中的处理是否正确? 但是原代码中的rem函是否有必要?因为在Python中,可以使用n % 10来得到余。例如,对于负n,比如n=-380,n%10得到0,而n//10得到-38。所以可以简化代码,不需要自定义rem函,直接使用%和//运算符。 例如,修改后的学方法: n = int(input()) reversed_num = 0 sign = 1 if n >=0 else -1 n = abs(n) while n > 0: reversed_num = reversed_num * 10 + n % 10 n = n // 10 reversed_num *= sign print(reversed_num) 但这样处理的话,例如输入n=-380,绝对值n=380,反转得到0+0→0*10+0=0,然后n=38;然后0*10+8=8,n=3;然后8*10+3=83,n=0。最后乘以符号-1,得到-83。正确。同时,输入n=1200,绝对值反转得到00021?不,循环处理是:n=1200 → 1200%10=0 → reversed_num=0*10+0=0,n=120 → 0*10+0=0,n=12 → 0*10+2=2,n=1 → 2*10+1=21 → 结束,输出21。正确。输入n=0,循环不会执行,直接输出0。正确。 所以,原引用3的代码可能存在对负处理的问题,或者可能正确?需要验证。例如,原代码中的rem函在n为负时是否正确? 原代码中,rem函计算余的方式是:r = n - k*10,其中k=int(n/10)。在Python中,int()对于负除法是向零取整还是向下取整?例如,n=-380,n/10=-38.0,int(n/10)=-38。k=-38,r=-380 - (-38)*10=0。正确。当n=-38时,n/10=-3.8,int(n/10)=-3,k=-3,r=-38 - (-3)*10 = -38+30=-8。正确。当n=-3时,n/10=-0.3,int(n/10)=0,r=-3 -0*10=-3。sum=0*10+0=0 → 在循环中,sum=sum*10 + rem(n)。第一次循环sum=0+0=0,n变成-38。第二次sum=0*10 + (-8)=-8,n变成-3。第三次sum=-8*10 + (-3)=-83,n变成0,循环结束。输出-83,正确。 所以原代码在Python中处理负是否正确?看起来是的,但可能在某些情况下有问题?例如,当n=-10时,反转后的结果应该是-1。原代码处理过程: n=-10 → rem(-10) → k=int(-10/10)=-1 → r=-10 - (-1)*10=0 → sum=0*10 +0=0 → n=int(-10/10)=-1 → sum=0*10 + (-1 - int(-1/10)*10 → n=-1时,k=int(-1/10)=0 → r=-1 -0*10=-1 → sum=0*10 + (-1)= -1 → n=int(-1/10)=0 → 循环结束,输出-1。正确。所以原代码似乎能正确处理负的情况。 但是用户提供的引用4中提到代码1超时,可能因为某些情况下循环次过多?或者在Python中,这样的循环效率足够吗?对于题目给定据范围,数字最多是10,循环10次,不会超时。因此,引用4中的超时可能是其他语言的实现问题,例如C++中可能用了低效的方法,而Python的循环在这种情况下足够快。 因此,学方法是可行的。另一种方法是字符串处理,例如: n = int(input()) s = str(n) if s[0] == '-': reversed_s = '-' + s[:0:-1].lstrip('0') or '0' else: reversed_s = s[::-1].lstrip('0') or '0' print(int(reversed_s)) 这里处理负的情况,例如输入-380,字符串为"-380",反转绝对值部分即s[:0:-1]是"083",然后lstrip('0')得到"83",加上负号得到"-83"。对于输入1200,反转得到"0021",lstrip('0')得到"21",如果反转后全零(如输入0),则or '0'确保输出0。 这种方法需要注意字符串反转后的处理,特别是去除前导零。例如,当反转后的字符串全为零时,lstrip('0')会变成空字符串,此时用or '0'来补零。例如,输入n=0时,反转后的字符串为'0',处理后保持0。 比较两种方法,字符串方法更简洁,但可能对于大处理效率不如学方法?不过题目中的据范围不大,两种方法都可以。Python中字符串处理通常比较高效,因此两种方法都可以接受。 用户可能需要看到两种方法的示例,以便选择最适合的方式。根据引用3中的代码,学方法已经给出,但可以优化。而字符串方法可能更简洁。 现在需要检查用户提供的引用3中的代码是否在某些情况下有问题,例如n=0的情况。在引用3的代码中,如果输入n=0,循环不会执行,sum保持0,输出0,正确。对于n=100,反转后得到001 → 1,sum的计算过程:第一次得到0,n=10;sum=0*10+0=0,n=1;sum=0*10+1=1,n=0,输出1,正确。 所以,用户提供的引用3中的代码是正确的,但可能可以优化,例如去掉自定义的rem函,直接使用%运算符。例如: n = int(input()) sum = 0 while n != 0: sum = sum * 10 + n % 10 n = int(n / 10) print(sum) 这样更简洁,不需要rem函。但需要验证处理负的情况。例如,n=-380时,n%10在Python中得到-0,但实际上在Python中,-380 %10 是0,因为-380 = (-38)*10 +0。所以,n%10的结果是正确的。例如: n = -380 while n !=0: print(n%10) n = int(n/10) 输出:0 → -38%10= -8 → -3%10=-3。所以,sum的计算过程会是: sum=0*10+0=0 → n=-38 sum=0*10 + (-38%10) → -8 → sum=-8 → n=-3 sum=-8*10 + (-3%10)= -83 → n=0 → 输出-83,正确。 但这里有一个问题,当n为负时,n%10的结果可能为负吗?例如,n=-38,n%10=2?或者在Python中,负取余的规则是什么? Python中的取余运算结果符号相同。例如,-380 //10 = -38(因为Python是向下取整),所以-380 %10 = -380 - (-38)*10 =0。而n=-38时,n//10=-4(因为-38/10=-3.8,向下取整到-4),所以n%10= -38 - (-4)*10 = 2。所以,此时sum的计算会出错。 哦,这里发现了问题。Python中的取余运算整除运算相关。例如,对于负,int(n/10)和n//10的结果可能不同。例如,在Python中: print(-380 // 10) # 输出-38 print(-380 % 10) # 输出0 print(-38 //10) # 输出-4,因为-38/10=-3.8,向下取整是-4 print(-38 %10) # 输出2,因为-38 = (-4)*10 +2 → 所以余是2. 所以,如果使用n%10来获取最后一,当n为负时,余可能不是我们想要的最后一数字。例如,n=-38时,n%10=2,而实际最后一数字是8,但符号是负的? 这会导致问题。例如,n=-38,在循环中,sum=sum*10 + (n%10) → 此时n%10=2,这显然不是我们想要的。所以,原引用3中的代码在Python中处理负时会出现错误。例如,输入n=-380,按上述学方法,sum=0*10+0=0 → n=-380//10=-38 → 但此时n=-38,n%10=2,sum=0*10+2=2 → 这显然是错误的,反转后的数字应该是-83,但这里得到2,然后继续处理n=-38//10=-4,n%10=6 → sum=2*10+6=26 → n=-4//10=-1 → sum=26*10 +9=269 → 等等,完全错误。 这说明原引用3中的代码在Python中处理负时存在错误,因为它依赖于int(n/10)的计算方式。而实际上,在Python中,应该使用n//10而不是int(n/10),因为int()函对于负会向零取整,而//运算符是向下取整。例如: n = -38 print(int(n/10)) # -3.8 → int转换得到-3 print(n//10) # -4 所以,原代码中使用int(n/10)会导致错误,正确的做法是使用n//10,但原代码中的rem函可能存在问题。例如,当n=-38时,k=int(n/10)=int(-3.8)=-3,然后r = n -k*10 → -38 - (-3)*10 = -38 +30 = -8。这得到正确余-8。但sum=sum*10 + (-8),这样会导致sum为负,但反转后的结果需要正确处理符号。例如,当处理n=-380时: 初始sum=0,n=-380 → rem(n)=0 → sum=0+0=0 → n=int(-380/10)= -38 → sum=0*10 + (-8) → sum=-8 → n=int(-38/10)=-3 → sum=-8*10 + (-3) → -83 → n=int(-3/10)=0 → 结束,输出-83。正确。 所以,原代码中的rem函在Python中是正确的,因为k=int(n/10)处理了向零取整,而余计算为n -k*10,这保证了余是正确的最后一数字(包括符号)。例如,当n=-38时,k=int(-38/10)=-3,r=-38 - (-3)*10= -38 +30= -8 → 正确的最后一数字是-8?或者应该是8? 这里存在矛盾。原代码的rem函返回的余可能为负,例如n=-38时,余是-8,而实际最后一数字是8,但符号是负。此时,sum会累加负,导致最终结果正确。例如,sum=0*10+0=0 → n=-38 → sum=0*10 + (-8)= -8 → n=-3 → sum=(-8)*10 + (-3) =-83 → 正确。所以,虽然余可能为负,但累加后的结果正确。例如,对于n=-380,处理后的结果是-83,正确。 因此,原代码在Python中是正确的,但这是因为在处理负时,余保留了符号,从而在累加时正确构造了反转后的负。例如,当处理n=-380时,余依次是0,-8,-3,sum的构造过程得到0 → -8 → -83,最后输出-83。这正确结果一致。 这说明原引用3的代码在Python中是正确的,但需要理解其处理负的方式。这可能容易引起困惑,因为通常反转数字的每一应该取其绝对值,但这里的处理方式通过允许余为负,并在累加时自然处理符号,从而得到正确结果。 另一种更直观的方法是处理绝对值,反转后再恢复符号。例如: n = int(input()) sign = 1 if n <0: sign = -1 n = -n reversed_num =0 while n>0: reversed_num = reversed_num*10 + n%10 n = n//10 reversed_num *= sign print(reversed_num) 这种方法处理负的步骤是:先取绝对值,反转,最后乘以符号。例如,n=-380 → 绝对值380,反转得到083 → 83 → 乘以-1得到-83。这样处理更直观,且避免了负的问题。因为此时n在循环中是正,每次取余得到的都是正的最后一。 这种方法是否正确?例如,输入n=380 → 反转得到083 → 83。输入n=1200 → 反转得到0021 → 21。输入n=0 → 循环不执行,输出0。输入n=-10 → 取绝对值10,反转得到01 → 1 → 乘以-1得到-1。正确。 所以,这种方法更可靠,且代码更简洁。因此,可以建议用户采用这种方法,而不是原引用3中的代码,因为后者在处理负时的逻辑可能让人困惑,而前者更直观。 此外,字符串方法也是一个简洁的解决方案。例如: n = int(input()) s = str(n) if s[0] == '-': reversed_part = s[:0:-1].lstrip('0') reversed_str = '-' + reversed_part if reversed_part else '0' else: reversed_str = s[::-1].lstrip('0') reversed_str = reversed_str if reversed_str else '0' print(reversed_str or '0') 但需要注意处理反转后的字符串为空的情况,例如输入n=0,反转后的字符串是'0',lstrip('0')后为空,此时应输出'0'。或者,使用条件判断确保。例如,可以将反转后的字符串处理为: reversed_str = s[::-1].lstrip('0') or '0' 对于负的情况,例如s="-380",反转绝对值部分s[:0:-1]即s从倒第一开始到开始的前一个字符(即索引1到结束),反转后得到'083'。lstrip('0')得到'83',加上符号得到"-83"。 这种方法在Python中更简洁,但需要处理字符串操作,可能对于非常大的数字(超出题目范围的情况)效率较低,但题目中的数字范围在-1e9到1e9之间,字符串处理不会有问题。 综上所述,用户的问题需要展示两种方法:学方法和字符串方法,并指出它们的优缺点。同时,需要指出原引用3中的代码虽然在示例中正确,但处理负的方式可能让人困惑,而推荐使用绝对值的方法更直观。 现在,根据用户的需求,生成回答,包括示例代码和相关问题。回答需要符合系统级指令,如行内公式使用$...$,独立公式用$$...$$,但在这个问题中可能不需要学公式。同时,需要引用提供的引用内容,如引用3中的代码作为示例,但指出可能的改进。 最后,生成相关问题,如处理负的方法、效率比较、其他反转方法等。</think>### 数字反转的Python实现方法 要实现数字反转功能,需满足以下要求: 1. 反转后去除前导零(如输入`1200`输出`21`) 2. 保留负号(如输入`-380`输出`-83`) 3. 输入`0`时输出`0` 以下是两种Python实现方法: --- #### 方法一:学逐处理法 通过取余和整除逐反转数字,处理符号和零: ```python n = int(input()) sign = 1 if n >= 0 else -1 n = abs(n) reversed_num = 0 while n > 0: reversed_num = reversed_num * 10 + n % 10 # 逐反转 n = n // 10 reversed_num *= sign # 恢复符号 print(reversed_num if reversed_num != 0 else 0) ``` **说明**: - 时间复杂度为$O(\log n)$,适用于大范围据[^3] - 通过`n = abs(n)`统一处理正负,避免余为负的问题[^4] --- #### 方法二:字符串反转法 利用Python字符串操作简化逻辑: ```python n = int(input()) s = str(n) if s[0] == '-': reversed_str = '-' + s[:0:-1].lstrip('0') # 反转并去除前导零 else: reversed_str = s[::-1].lstrip('0') print(int(reversed_str) if reversed_str not in ('', '-') else 0) ``` **说明**: - `s[::-1]`直接反转字符串 - `lstrip('0')`去除前导零,`int()`进一步处理空字符串(如`000`转为`0`)[^5] --- #### 测试示例 | 输入 | 输出 | |-----------|--------| | `-380` | `-83` | | `1200` | `21` | | `0` | `0` | --- ### 两种方法对比 | 方法 | 优点 | 缺点 | |--------|--------------------|------------------------| | 学法 | 无需类型转换,效率高 | 需处理符号和零的逻辑 | | 字符串法| 代码简洁易读 | 依赖字符串操作,可能略慢 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值