
回文数问题,也就是从左或者从右开始写,形式完全一样的数(或者叫对称数),例如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