回文数问题,也就是从左或者从右开始写,形式完全一样的数(或者叫对称数),例如909,21321这种.SPOJ的PALIN问题就是求大于给定数字的下一个回文数.
这个问题在处理时,有多种办法.
1. 可以用循环,不断+1,直到字符串表示的从左到右与从右到左完全相同;
2. 分析规律来处理原字符串.主要记录下这种办法.
要最终的结果是回文数,那么分别从头尾开始看,对应的数字两两都是相等的.
先看第一位,如果结尾数字大于第一位,那么最终的回文数,倒数第二位至少要+1,例如809,结果的倒数第二位肯定是比0大的最小整数1.因此解决思路就是:定义一个进位计数,如果前面第i个位置数字小于倒数第i个位置的数字,那么倒数第(i+1)位数字必须加1.值得注意的地方是,数字加1时要考虑9的进位问题,如果每个数字都是9,一直要进到最前面去,这时候由于前面的第1到第i个数字都被进位改变,因此倒数第1到倒数第i个已经匹配好的数字又需要重新匹配.好在python的整数范围非常大,而且字符串与数字的转换非常方便,因此只要截取第1位到倒数第(i-1)位,转为整数后加1即可.
一个要注意的地方是,python的string是immutable类型,虽然可以像list一样切片运算,但是不能inplace修改字符串的内容,也就是下面的操作时无效的:
s = 'abc' ; s[0] = 'c' >> TypeError: 'str' object does not support item assignment
判断回文数的函数:
#! /usr/bin/env python # coding=utf-8 def GetNextPalin(s): s = str(int(s)+1) slen = len(s) result = [int(c) for c in s] # process last digit prev = result[0]<result[-1] and 1 or 0 # add 1 to the num except last digits result[-1] = result[0] result = [int(c) for c in str(int(''.join([str(c) for c in result[:-1]]))+prev)]+result[-1:] # prevent cases like 899, 49999 # make sure the last digit is same as the first one prev = result[0]<result[-1] and 1 or 0 result[-1] = result[0] # loop the others for i in range(1,slen/2): result = [int(c) for c in str(int(''.join([str(c) for c in result[:-i]]))+prev)]+result[-i:] if result[i]<result[-i-1]: result[i] += 1 prev = 1 else: prev = 0 result[-i-1] = result[i] # odd length, process the center digit if slen%2!=0 and result[-1]==result[0]: result[slen/2] += prev result[slen/2] %= 10 # it may be 9, so only get the last digits # return result in string return ''.join([str(c) for c in result]) # test cases print GetNextPalin('808') print GetNextPalin('898') print GetNextPalin('2133') print GetNextPalin('48998') print GetNextPalin('49888') print GetNextPalin('79998')
测试结果:
818 909 2222 49094 49894 80008
No comments :
Post a Comment