Python (帮助)在给定的数字字符串中查找的代码
拉马努扬非常喜欢玩数字游戏。一天拉马努扬和 安妮什玩了一个游戏。拉马努扬给了安妮什一个数字串,然后问道 让他找到所有大小不同的子串,最多六个 首要的安妮什擅长数学,如果他能 Ramanujan为他提供的所有输入集的解决方案,Anish赢得 游戏你的任务是帮助安妮什赢得比赛 输入格式: 第一行包含T,测试用例的数量。每个测试用例 包含大小为N的字符串,该字符串仅包含整数 约束条件:Python (帮助)在给定的数字字符串中查找的代码,python,Python,拉马努扬非常喜欢玩数字游戏。一天拉马努扬和 安妮什玩了一个游戏。拉马努扬给了安妮什一个数字串,然后问道 让他找到所有大小不同的子串,最多六个 首要的安妮什擅长数学,如果他能 Ramanujan为他提供的所有输入集的解决方案,Anish赢得 游戏你的任务是帮助安妮什赢得比赛 输入格式: 第一行包含T,测试用例的数量。每个测试用例 包含大小为N的字符串,该字符串仅包含整数 约束条件: 1你没有达到时限。在我的基于Xeon的系统上,你的prime函数可以以每秒8次的速度处理10^6左右的prime。由
1你没有达到时限。在我的基于Xeon的系统上,你的
prime
函数可以以每秒8次的速度处理10^6左右的prime。由于您必须处理多达10^7个整数的列表,因此使用此类素数需要2周的时间。简而言之,您需要研究更快的方法来确定一个数字是否为素数
首先,有两个简单的限制将大大加快速度:
如果您想要更高的速度和复杂度,请查看用于快速素数检测的Rabin-Miller算法的实现。它是“唯一”概率的,但已经证明,对于128位整数,k=7(检查数量)时具有100%的准确率。有不同的方法使代码更快。例如,
prime
功能的加速是:
def isPrimeX(n):
if n in [2,3]: return True
if n % 2 == 0 or n % 3 == 0: return False
needCheckTill = int(math.sqrt(n))
for i in range(6, needCheckTill+2, 6):
if n % (i-1) == 0 or n % (i+1) == 0:
return False
return True
为了测试prim编号,您不需要将每个编号与此编号进行核对。事实上,只检查prim数就足够了,直到可能数的平方根为止。上述代码还利用了一个事实,即所有大于3的prim数字都可以用6n±1的形式写入(请参阅)
考虑到这一点,您可能会看到另一个加速。我们可以缓存从1到sqrt(10E7)的原始数,并使用Eratosthenes算法的筛选来计算它们:
# get a list of all prim numbers between 1 and 10E7
import math
def isPrim(n, belowPrims):
limit = int(math.sqrt(n))
for prim in belowPrims:
if prim > limit: break
if n % prim == 0: return False
return True
def calcPrims():
yield 2
yield 3
toTest, nextN = [], 6
while True:
p1 = nextN - 1
if isPrim(p1, toTest):
yield p1
toTest.append(p1)
p2 = nextN + 1
if isPrim(p2, toTest):
yield p2
toTest.append(p2)
nextN += 6
limit = int(math.sqrt(10 ** 7)) + 1
listOfPrims = []
for prim in calcPrims():
if prim > limit:
break
listOfPrims.append(prim)
您的其余代码也可以得到进一步优化 除了@Prune的数学改进之外,还有一些其他编程改进 首先,在
get_all_substring()
中,没有必要让alist
真正成为一个列表,而不仅仅是一个集合,它甚至不需要在最后更改。使用.add()
而不是.append()
其次,您可以通过以下两种方式节省构建列表a
的时间:
- 除非我弄错了,否则不需要分类。尽管如果您使用@Prune建议存储已找到的素数,排序可能会有所帮助
- 我们可以在计算完子字符串后立即将其转换为整数。所以我们会有类似于
。这样可以节省内存,也可以很容易地比较它们是否太长。因为我们知道一个9位数的最大值(以10为基数),我们可以简单地检查它是否更大,这是非常快的<代码>i>999999alist.add(int(string[i:j+1]))
- 首先不要添加太长的条目。有一个很好的,蟒蛇式的方法可以做到这一点。我们可以使用条件列表理解
>>> my_list = [i for i in range(10)]
>>> print(my_list)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
可以添加一个条件,以便只添加我们想要的元素:
>>> my_list = [i for i in range(10) if i%2 == 0]
>>> print(my_list)
[0, 2, 4, 6, 8]
这相当于以下内容:
my_list = []
for i in range(10):
if i%2 == 0:
my_list.append(i)
综合起来,我们只需要一行就可以生成一个:
a = [val for val in get_all_substrings(input().strip) if val > 999999]
我希望通过根本不生成那些太长的子字符串,并避免创建重复的子字符串,您可以做得更好,因为这样可以消除对集合的需要。这是代码战还是其他原因造成的问题?如果你得到了正确的结果,但是超时了,那是因为你的程序是正确的,但是太慢了。你需要想出加速的方法,甚至可能是一个完全不同的算法。你的方法是什么?非常感谢你,你消除了我的很多疑问。谢谢你,这真的很有帮助,先生。@Dbug On stackoverflow“谢谢”正在接受+向上投票的答案;)不过还是欢迎你;)谢谢,这给了我一个关于代码优化的想法,我希望在将来的代码中更好地应用它们
a = [val for val in get_all_substrings(input().strip) if val > 999999]