python单循环整除8_一个循环?Python

所以我写了这个函数给出了可能的数字,它必须找到构成给定数字的可能数字内的两个数字.但是,我仍在学习

Python(一种非常好的语言),所以我只能使用一组有限的函数.

我创建了这个函数:

def sumPair(theList, n):

theList = charCount(theList) #charCount is a function i made to convert the list into a dictionary

for i in theList:

for a,b in theList.iteritems():

print a,b

if a + i == n:

if theList[b] > 1:

return [i, b]

if a != i:

return [i, b]

return "[]"

print sumPair([6,3,6,8,3,2,8,3,2], 11)

就像我说的,它找到了两个加起来给定数字的数字. charCount是我编写的一个函数,它将数组添加到字典中.

在这个程序中,我确保值大于1,以防添加的数字相同.有时如果它检查10的总和并给你5的数字,它只会将5添加到自身并返回10.这就是if theList [b]> 1:

在那儿.

为什么我在这里?我的导师对两个循环不满意.我花了5个小时进行故障排除,无处可去.我需要将此程序转换为单循环程序.

我整天都花在这上面,我不是想让你做我的作业,我真的被困住了,我需要你的帮助.我听说我应该检查是否存在一个密钥才能完成.

用铅笔和纸或者甚至只看纸上的数字行,如何用手来做这个问题总是有助于思考问题.然而,更好的解决方案起初可能看起来过于复杂,而且它们的优势可能不是那么清楚 – 见

gnibbler’s solution(他的答案是我个人的赢家,见下文).

首先,您需要将一个数字与所有其他数字进行比较.然后使用其余的第二个数字等.当使用朴素方法时,使用单个处理器时无法避免两个嵌套循环.那么时间复杂度总是为O(n ^ 2),其中n是序列的长度.事实是,一些循环可能隐藏在像list或index.index()这样的操作中,这在原则上不能使解决方案更好.

想象一下数字的笛卡尔积 – 它由数字的夫妻组成.这些夫妇中有n ^ 2个,但是相对于加法操作的可交换性质,大约一半是相同的,并且其中n个是与itsef的对.这意味着您只需要检查n ^ 2/2 – n对.如果它们适合测试,最好避免循环遍历不必要的对,而不是稍后进行测试:

for each first element in theList:

for each second element in the rest of theList from the checked one on:

if the first and the second elements give the solution:

report the result

possibly early break if only the first should be reported

对于已选中的列表的其余部分使用切片,使用第一个(也可能是第二个)循环中的enumerate()来了解索引.

最小化循环中的操作总是好主意.想想内循环体是最多次完成的.这样,您可以在进入内循环之前计算搜索到的数字:searching = sum – first.然后,如果在列表的其余部分中搜索,则第二个循环加上if可以替换为:

[此处出现更多完整解决方案后编辑]

这是找到第一次出现或无的O(n ^ 2)解决方案(纯Python,简单,没有图书馆,内置函数和仅切片,几行):

def sumPair(theList, n):

for index, e in enumerate(theList): # to know the index for the slicing below

complement = n - e # we are searching for the complement

if complement in theList[index+1:]: # only the rest is searched

return e, complement

print sumPair([6,3,6,8,3,2,8,3,2], 11)

[在gnibbler评论切片和复制后添加]

gnibbler是关于切片的.切片是副本. (问题是切片是否未使用“写入时复制”技术进行优化 – 我不知道.如果是,那么切片将是一个廉价的操作.)为了避免复制,可以使用列表进行测试.index()方法,允许传递起始索引.唯一奇怪的是,当找不到该项时,它会引发ValueError异常.这样,if补码……必须由try替换…除外:

def sumPair2(theList, n):

for ind, e in enumerate(theList):

try:

theList.index(n - e, ind + 1)

return e, n - e

except ValueError:

pass

Gnibbler的评论让我更多地思考这个问题.事实是集合可以接近O(1)来测试它是否包含元素和O(n)来构造集合.对于非数字元素(其中集合类型不能实现为位数组)并不清楚.当哈希数组进入游戏并且可能使用其他技术解决可能的冲突时,质量取决于实现.

如有疑问,请测量.这里gnibbler的解决方案稍作修改,与其他解决方案一样:

import timeit

def sumPair(theList, n):

for index, e in enumerate(theList):

if n - e in theList[index+1:]:

return e, n - e

def sumPair2(theList, n):

for ind, e in enumerate(theList):

try:

theList.index(n - e, ind + 1)

return e, n - e

except ValueError:

pass

def sumPair_gnibbler(theList, n):

# If n is even, check whether n/2 occurs twice or more in theList

if n%2 == 0 and theList.count(n/2) > 1:

return n/2, n/2

theSet = set(theList)

for e in theSet:

if n - e in theSet:

return e, n - e

该问题的原始数字用于第一次测试.当无法找到解决方案时,n = 1会导致最坏的情况:

theList = [6,3,6,8,3,2,8,3,2]

n = 11

print '---------------------', n

print sumPair(theList, n),

print timeit.timeit('sumPair(theList, n)', 'from __main__ import sumPair, theList, n', number = 1000)

print sumPair2(theList, n),

print timeit.timeit('sumPair2(theList, n)', 'from __main__ import sumPair2, theList, n', number = 1000)

print sumPair_gnibbler(theList, n),

print timeit.timeit('sumPair_gnibbler(theList, n)', 'from __main__ import sumPair_gnibbler, theList, n', number = 1000)

n = 1

print '---------------------', n

print sumPair(theList, n),

print timeit.timeit('sumPair(theList, n)', 'from __main__ import sumPair, theList, n', number = 1000)

print sumPair2(theList, n),

print timeit.timeit('sumPair2(theList, n)', 'from __main__ import sumPair2, theList, n', number = 1000)

print sumPair_gnibbler(theList, n),

print timeit.timeit('sumPair_gnibbler(theList, n)', 'from __main__ import sumPair_gnibbler, theList, n', number = 1000)

它在我的控制台上产生以下输出:

--------------------- 11

(3, 8) 0.00180958639191

(3, 8) 0.00594907526295

(8, 3) 0.00124991060067

--------------------- 1

None 0.00502748219333

None 0.026334041968

None 0.00150958864789

从短的数字序列和一个特殊情况来看,从时间复杂性的角度来说,质量是不可能的.无论如何,gnibbler的解决方案赢了.

当序列包含唯一值时,gnibbler的解决方案使用最多的内存.让我们尝试更长的包含0,1,2,…,9999的序列.n等于11和3000表示具有解决方案的任务.对于n等于30000的情况,无法找到这对数字.必须检查所有元素 – 最坏的情况:

theList = range(10000)

n = 11

print '---------------------', n

print sumPair(theList, n),

print timeit.timeit('sumPair(theList, n)', 'from __main__ import sumPair, theList, n', number = 100)

print sumPair2(theList, n),

print timeit.timeit('sumPair2(theList, n)', 'from __main__ import sumPair2, theList, n', number = 100)

print sumPair_gnibbler(theList, n),

print timeit.timeit('sumPair_gnibbler(theList, n)', 'from __main__ import sumPair_gnibbler, theList, n', number = 100)

n = 3000

print '---------------------', n

print sumPair(theList, n),

print timeit.timeit('sumPair(theList, n)', 'from __main__ import sumPair, theList, n', number = 100)

print sumPair2(theList, n),

print timeit.timeit('sumPair2(theList, n)', 'from __main__ import sumPair2, theList, n', number = 100)

print sumPair_gnibbler(theList, n),

print timeit.timeit('sumPair_gnibbler(theList, n)', 'from __main__ import sumPair_gnibbler, theList, n', number = 100)

n = 30000

print '---------------------', n

print sumPair(theList, n),

print timeit.timeit('sumPair(theList, n)', 'from __main__ import sumPair, theList, n', number = 100)

print sumPair2(theList, n),

print timeit.timeit('sumPair2(theList, n)', 'from __main__ import sumPair2, theList, n', number = 100)

print sumPair_gnibbler(theList, n),

print timeit.timeit('sumPair_gnibbler(theList, n)', 'from __main__ import sumPair_gnibbler, theList, n', number = 100)

请注意,序列要长得多.该测试仅重复100次,以便在合理的时间内得到结果. (除非您将其除以数字,否则时间无法与之前的测试进行比较.)它在我的控制台上显示以下内容:

--------------------- 11

(0, 11) 0.00840137682165

(0, 11) 0.00015695881967

(0, 11) 0.089894683992

--------------------- 3000

(0, 3000) 0.0166750746034

(0, 3000) 0.00966040735374

(0, 3000) 0.12532849753

--------------------- 30000

None 180.328006493

None 163.651082944

None 0.204691100723

对于非最坏情况,gnibbler的解决方案似乎很慢.原因是它需要经历所有序列的准备阶段.天真的解决方案在第一次通过的大约三分之一中找到了数字.什么告诉anythig是最糟糕的情况. gnibbler的解决方案快了大约1000倍,并且对于更长的序列,差异会增加. Gnibbler的解决方案是明显的赢家.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值