加速Python3.4代码
我有一个问题,我需要在给定的数字之后找到下一个最大的回文,但是我遇到了运行时间超过1秒的问题。有什么方法可以加快这个代码的速度吗加速Python3.4代码,python,performance,python-3.x,Python,Performance,Python 3.x,我有一个问题,我需要在给定的数字之后找到下一个最大的回文,但是我遇到了运行时间超过1秒的问题。有什么方法可以加快这个代码的速度吗 inp = input() if inp == '9' * len(inp): print('1' + ('0' * (len(inp) - 1)) + '1') #ran into a problem where 999 would give 9109 else: num = list(inp) oldnum = int(inp) if len(num) %
inp = input()
if inp == '9' * len(inp):
print('1' + ('0' * (len(inp) - 1)) + '1') #ran into a problem where 999 would give 9109
else:
num = list(inp)
oldnum = int(inp)
if len(num) % 2 == 0: #for even length numbers
for i in range(len(num) // 2):
num[len(num) // 2 + i] = num[len(num) // 2 - 1 - i]
if int("".join(num)) > oldnum:
print("".join(num))
else:
#sometimes the palindrome was smaller eg: 1199 --> 1111
num[len(num) // 2 - 1] = str(int(num[len(num) // 2 - 1]) + 1)
num[len(num) // 2] = str(int(num[len(num) // 2]) + 1)
print("".join(num))
else: #basically the same but for odd length numbers
for i in range(len(num) // 2):
num[len(num) // 2 + 1 + i] = num[len(num) // 2 - 1 - i]
if int("".join(num)) > oldnum:
print("".join(num))
else:
num[len(num) // 2] = str(int(num[len(num) // 2]) + 1)
print("".join(num))
虽然你的代码花了我不到一秒钟的时间。但为什么这么多代码只是为了找到一个普通的机场。为什么不简单呢
def next_palindrome(num):
while True:
if str(num) == str(num)[::-1]:
break
num += 1
return num
下面是我将如何分解它
# simple version, easy to understand and fast enough
# up to maybe a thousand digits
def next_palindrome(n):
"""
Find the first integer p such that p > n and p is palindromic
"""
# There are two forms of palindrome:
# even number of digits, abccba
# odd number of digits, abcba
# Find abc
s = str(n)
abc = s[:(len(s) + 1) // 2]
# There are six possibilites for p:
#
# abcpq < abcba -> p = abcba
# abcpq >= abcba -> p = ab(c + 1)ba (with carries as needed)
# abcpqr == 999999 -> p = 1000001 *(num digits + 1)
#
# abcpqr < abccba -> p = abccba
# abcpqr >= abccba -> p = ab(c+1)(c+1)ba (with carries as needed)
# abcpq == 99999 -> p = 100001 *(num digits + 1)
#
# *Note that the even-number-of-9s case is properly handled by
# odd-digits-with-carry, but odd-number-of-9s needs special handling
#
# Make basis substrings
cba = abc[::-1]
ba = cba[1:]
abc1 = str(int(abc) + 1)
cba1 = abc1[::-1]
ba1 = cba1[1:]
# Assemble candidate values
candidates = [
int(abc + ba), # abcba
int(abc1 + ba1), # ab(c+1)ba
int(abc + cba), # abccba
int(abc1 + cba1), # ab(c+1)(c+1)ba
int(abc1[:-1] + ba1) # handles odd-number-of-9s
]
# Find the lowest candidate > n
return min(c for c in candidates if c > n)
def main():
while True:
n = int(input("\nValue for n (or -1 to quit): "))
if n == -1:
break
else:
print("Next palindrome is {}".format(next_palindrome(n)))
if __name__ == "__main__":
main()
编辑:我以为你说的可能是100位数。一百万位数字使我们有必要花更多的时间来减少字符串操作和类型转换的数量,如下所示:
# Super-efficient version
# for playing with million-digit palindromes
def str_lt(x, y):
"""
Take two integer strings, `x` and `y`,
return int(`x`) < int(`y`)
"""
return len(x) < len(y) or x < y
def str_add_1(n):
"""
Given an integer string `n`,
return str(int(n) + 1)
"""
# find the first non-9 digit, starting from the right
for i in range(len(n) - 1, -1, -1):
if n[i] != '9':
return n[:i] + str(int(n[i]) + 1) + '0' * (len(n) - i - 1)
# string was all 9s - overflow
return '1' + '0' * len(n)
def next_palindrome(n):
"""
For non-negative integer `n` (as int or str)
find the first integer p such that p > n and p is palindromic
Return str(p)
Note: `n` must be well-formed, ie no leading 0s or non-digit characters
"""
# Make sure n is a string
if not isinstance(n, str):
n = str(n)
# There are three forms of palindrome:
# single digit, x (ab == '')
# even number of digits, abba ( x == '')
# odd number of digits, abxba ( x is single digit)
#
if len(n) == 1:
# take care of single digit case
return '11' if n == '9' else str_add_1(n)
else:
# There are six possibilites for p:
#
# (1) abqr < abba -> p = abba
# (2) abqr >= abba -> p = a(b+1)(b+1)a (with carries as needed)
# (3) abqr == 9999 -> p = 10001 (carry results in overflow)
#
# (4) abxqr < abxba -> p = abxba
# (5) abxqr >= abxba -> p = ab(x + 1)ba (with carries as needed)
# (6) abxqr == 99999 -> p = 100001 (carry results in overflow)
#
# Find ab, x, qr
half = len(n) // 2
ab = n[ : half]
x = n[ half:-half] # a 0- or 1-digit string
qr = n[-half: ]
ba = ab[::-1]
if str_lt(qr, ba):
# solve cases (1) and (4)
return "".join([ab, x, ba])
if x == '9':
# do manual carry from x
ab1 = str_add_1(ab)
ba1 = ab1[::-1]
if len(ab1) > len(ab):
# carry results in overflow - case (6)
return ab1 + ba1
else:
# carry but no overflow - case (5)
return "".join([ab1, '0', ba1])
if x:
# no carry - case (5)
return "".join([ab, str_add_1(x), ba])
# x == ''
ab1 = str_add_1(ab)
ba1 = ab1[::-1]
if len(ab1) > len(ab):
# carry results in overflow - case (3)
return ab1[:-1] + ba1
else:
# no overflow - case (2)
return ab1 + ba1
#超高效版本
#用于处理百万位回文
def STRU lt(x,y):
"""
取两个整数字符串,`x`和`y`,
返回int(`x`)n且p是回文的
返回str(p)
注意:`n`必须格式正确,即无前导0或非数字字符
"""
#确保n是一个字符串
如果不存在(n,str):
n=str(n)
#回文有三种形式:
#单个数字,x(ab='')
#偶数位数,abba(x='')
#奇数位数,abxba(x为一位数)
#
如果len(n)==1:
#处理一位数的案件
如果n==9,则返回'11',否则str\u add\u 1(n)
其他:
#p有六种可能性:
#
#(1)abqrp=abba
#(2)abqr>=abba->p=a(b+1)(b+1)a(根据需要进行进位)
#(3)abqr==9999->p=10001(进位导致溢出)
#
#(4)abxqrp=abxba
#(5)abxqr>=abxba->p=ab(x+1)ba(根据需要带进位)
#(6)abxqr==99999->p=100001(进位导致溢出)
#
#找到ab,x,qr
half=len(n)//2
ab=n[:一半]
x=n[half:-half]#0或1位字符串
qr=n[-一半:]
ba=ab[:-1]
如果str_lt(qr,ba):
#解决案例(1)和(4)
返回“”。加入([ab,x,ba])
如果x=='9':
#是否从x进行手动携带
ab1=str\U add\U 1(ab)
ba1=ab1[:-1]
如果len(ab1)>len(ab):
#溢出中的进位结果-案例(6)
返回ab1+ba1
其他:
#携带但不溢出-箱(5)
返回“”。加入([ab1,'0',ba1])
如果x:
#无手提行李-箱子(5)
返回“”。加入([ab,str\u add\u 1(x),ba])
#x==''
ab1=str\U add\U 1(ab)
ba1=ab1[:-1]
如果len(ab1)>len(ab):
#溢出中的进位结果-案例(3)
返回ab1[:-1]+ba1
其他:
#无溢出-案例(2)
返回ab1+ba1
在我的机器上,这可以在不到0.002秒的时间内找到一个百万位数的回文(而你的代码大约为18.5秒)。这里的问题可能更合适:使用探查器找出时间首先花在哪里。因为,如果他的算法正确,它将是O(log(n))而不是O(sqrt(n))-对于较大的输入,速度要快上千倍。如果输入的是10^6位数字,速度会变得非常慢。这很有帮助,但输入0-8时会产生错误,对于10^6位数字,速度仍然太慢。谢谢,我今晚会看一看。效果非常好。我能问一下你是做什么的吗?今年我在学校学习python,并打算继续学习。我想知道我需要多长时间才能达到你的水平。我只使用Python 3或4年,但在此之前我有很长的编程历史;我从1981年开始学习Vic-20,我想从那以后每隔两三年我就会学一门新语言。掌握的一部分是真正熟悉一种语言、它的标准库和习惯用法;部分是理解算法、数据结构和模式,以及如何有效地解决问题;part在不同的语言家族和风格方面有着丰富的经验:汇编语言、声明式语言(Prolog或SQL)、函数式语言(Scala或Haskell)、面向对象语言(Eiffel或Java)、硬件语言(VHDL)等等。哇,那么你编程的时间比我还多了近20年。看来我还有很长的路要走,但我会坚持下去。谢谢。
# Super-efficient version
# for playing with million-digit palindromes
def str_lt(x, y):
"""
Take two integer strings, `x` and `y`,
return int(`x`) < int(`y`)
"""
return len(x) < len(y) or x < y
def str_add_1(n):
"""
Given an integer string `n`,
return str(int(n) + 1)
"""
# find the first non-9 digit, starting from the right
for i in range(len(n) - 1, -1, -1):
if n[i] != '9':
return n[:i] + str(int(n[i]) + 1) + '0' * (len(n) - i - 1)
# string was all 9s - overflow
return '1' + '0' * len(n)
def next_palindrome(n):
"""
For non-negative integer `n` (as int or str)
find the first integer p such that p > n and p is palindromic
Return str(p)
Note: `n` must be well-formed, ie no leading 0s or non-digit characters
"""
# Make sure n is a string
if not isinstance(n, str):
n = str(n)
# There are three forms of palindrome:
# single digit, x (ab == '')
# even number of digits, abba ( x == '')
# odd number of digits, abxba ( x is single digit)
#
if len(n) == 1:
# take care of single digit case
return '11' if n == '9' else str_add_1(n)
else:
# There are six possibilites for p:
#
# (1) abqr < abba -> p = abba
# (2) abqr >= abba -> p = a(b+1)(b+1)a (with carries as needed)
# (3) abqr == 9999 -> p = 10001 (carry results in overflow)
#
# (4) abxqr < abxba -> p = abxba
# (5) abxqr >= abxba -> p = ab(x + 1)ba (with carries as needed)
# (6) abxqr == 99999 -> p = 100001 (carry results in overflow)
#
# Find ab, x, qr
half = len(n) // 2
ab = n[ : half]
x = n[ half:-half] # a 0- or 1-digit string
qr = n[-half: ]
ba = ab[::-1]
if str_lt(qr, ba):
# solve cases (1) and (4)
return "".join([ab, x, ba])
if x == '9':
# do manual carry from x
ab1 = str_add_1(ab)
ba1 = ab1[::-1]
if len(ab1) > len(ab):
# carry results in overflow - case (6)
return ab1 + ba1
else:
# carry but no overflow - case (5)
return "".join([ab1, '0', ba1])
if x:
# no carry - case (5)
return "".join([ab, str_add_1(x), ba])
# x == ''
ab1 = str_add_1(ab)
ba1 = ab1[::-1]
if len(ab1) > len(ab):
# carry results in overflow - case (3)
return ab1[:-1] + ba1
else:
# no overflow - case (2)
return ab1 + ba1