我必须通过分而治之算法从列表中找到第二大数字和最大数字。问题是一切都是正确的,除了我使用像a和b这样的索引的部分。因为它工作得更快。价格便宜。不需要重写代码或发送其他代码和方法。请帮助我解决它,如果你可以..任何帮助任何想法欢迎。感谢
#!/usr/local/bin/python2.7
def two_max(arr,a,b):
n = len(arr)
if n==2:
if arr[0]<arr[1]:
return (arr[1], arr[0])
else:
return (arr[0], arr[1])
(greatest_left, sec_greatest_left) = two_max(arr,a (a+b)/2)
(greatest_right, sec_greatest_right) = two_max(arr,(a+b)/2,b)
if greatest_left < greatest_right:
greatest = greatest_right
if greatest_left < sec_greatest_left:
return (greatest, sec_greatest_left)
else:
return (greatest, greatest_left)
else:
greatest = greatest_left
if greatest_right < sec_greatest_right: # Line 4
return (greatest, sec_greatest_right)
else:
return (greatest, greatest_right)
答案 0 :(得分:1)
你为什么不这样做:
>>> def getIlargest(arr, i):
if (i <= len(arr) and i > 0):
return sorted(arr)[-i]
>>> a = [1,3,51,4,6,23,53,2,532,5,2,6,7,5,4]
>>> getIlargest(a, 2)
53
我更进一步,测试了3种方法:
getIlargestVer2
sorted
函数 - getIlargestVer1
heapIlargest
作为@abarnert建议。结果:
对于大小从1到大约5000 sorted
的数组是最好的,对于较大的数组,heapq.nlargest
用法是赢家:
绘制大小介于[1*150, 55*150]
:
*阵列之间的全扫描,大小为[1 * 150,300 * 150]:*
我使用的代码如下,3个方法实现在setup
字符串:
setup = """
import heapq, random
a = random.sample(xrange(1<<30), 150)
a = a * factor
class ILargestFunctions:
# taken from [wiki][3] and was rewriting it.
def counting_sort(self, array, maxval):
m = maxval + 1
count = {}
for a in array:
if count.get(a, None) is None:
count[a] = 1
else:
count[a] += 1
i = 0
for key in count.keys():
for c in range(count[key]):
array[i] = key
i += 1
return array
def getIlargestVer1(self, arr, i):
if (i <= len(arr) and i > 0):
return sorted(arr)[-i]
def getIlargestVer2(self, arr, i):
if (i <= len(arr) and i > 0):
return self.counting_sort(arr, max(arr))[-i]
def heapIlargest(self, arr, i):
if (i <= len(arr) and i > 0):
return heapq.nlargest(i,arr)
n = ILargestFunctions()
"""
主线触发性能计数并绘制收集的数据:
import timeit
import numpy as np
import matplotlib.pyplot as plt
if __name__ == "__main__":
results = {}
r1 = []; r2 = []; r3 = [];
x = np.arange(1,300,1)
for i in xrange(1,300,1):
print i
factorStr = "factor = " + str(i) + ";"
newSetupStr = factorStr + setup
r1.append(timeit.timeit('n.getIlargestVer1(a, 100)', number=200, setup=newSetupStr))
r2.append(timeit.timeit('n.getIlargestVer2(a, 100)', number=200, setup=newSetupStr))
r3.append(timeit.timeit('n.heapIlargest(a, 100)', number=200, setup=newSetupStr))
results[i] = (r1,r2,r3)
p1 = plt.plot(x, r1, 'r', label = "getIlargestVer1")
p2 = plt.plot(x, r2, 'b' , label = "getIlargestVer2")
p3 = plt.plot(x, r3, 'g' , label = "heapIlargest")
plt.legend(bbox_to_anchor=(1.05, 1), loc=1, borderaxespad=0.)
plt.show()
答案 1 :(得分:1)
最大的问题是你永远不会接近你的递归基础案例。
基本案例是len(arr) == 2
。但每当你打电话给自己时,你只需按原样arr
传递:
(greatest_left, sec_greatest_left) = two_max(arr,a,(a+b)/2)
(greatest_right, sec_greatest_right) = two_max(arr,(a+b)/2,b)
(请注意,我猜测第一个中的逗号,因为当你发布它时,你实际上将数字a
称为函数,这不太可能做任何有用的事情......)< / p>
因此,您的基本案例应考虑a
和b
,如下所示:
if b-a == 2:
if arr[a]<arr[a+1]:
return (arr[a+1], arr[a])
else:
return (arr[a], arr[a+1])
...或者你应该发送一片arr
而不是整件事 - 在这种情况下你首先不需要a
和b
:
(greatest_left, sec_greatest_left) = two_max(arr[:len(a)/2])
(greatest_right, sec_greatest_right) = two_max(arr[len(a)/2:])
任何一方都会解决你的第一个问题。当然,对于大多数输入,该功能仍然不工作。实际上,只有当列表的长度为2的幂时,它才有效。
如果这不是一个足够好的提示,如何解决它:如果b-a
是3,会发生什么?显然你不能将它分成两半,两者的大小都是2或更大。因此,您需要为b-a == 1
编写另一个基本案例,并返回某些,这将使算法的其余部分工作。
答案 2 :(得分:0)
@ 0x90有正确的想法,但他让它逆转了。
def find_i_largest_element(seq, i):
if (i <= len(seq) and i > 0):
s = sorted(seq, reverse=True)
return s[i-1]
顺便问一下,这是一项家庭作业吗?如果是这样,你必须使用的算法背后的整个想法是什么?