回答
我能想到的是排序的原始列表,然後選擇第一個和最後一個元素最快的方法。這避免了多次循環,但它確實會破壞列表的原始結構。這可以通過簡單地複製列表並僅對複製列表進行排序來解決。我很好奇,如果這是不是僅僅使用MAX()和MIN()這個簡單的例子腳本較慢:
import time
l = [1,2,4,5,3]
print "Run 1"
t1 = time.time()
print "Min =", min(l)
print "Max =", max(l)
print "time =", time.time() - t1
print ""
print "l =", l
print ""
l = [1,2,4,5,3]
l1 = list(l)
print "Run 2"
t1 = time.time()
l1.sort()
print "Min =", l1[0]
print "Max =", l1[-1]
print "time =", time.time() - t1
print ""
print "l =", l
print "l1 =", l1
print ""
l = [1,2,4,5,3]
print "Run 3"
minimum = float('inf')
maximum = float('-inf')
for item in l:
if item < minimum:
minimum = item
if item > maximum:
maximum = item
print "Min =", minimum
print "Max =", maximum
print "time =", time.time() - t1
print ""
print "l =", l
出人意料的是,第二種方法是通過我的電腦上10ms左右的速度更快。不知道這對非常大的列表會有多大的效果,但這種方法對於您提供的示例列表至少更快。
我在我的計時腳本中添加了@Martijn Pieters的簡單循環算法。 (由於時間將是值得探討在這個問題上唯一重要的參數)我的結果是:
Run 1: 0.0199999809265s
Run 2: 0.00999999046326s
Run 3: 0.0299999713898s
編輯:timeit模塊納入的時機。
import timeit
from random import shuffle
l = range(10000)
shuffle(l)
def Run_1():
#print "Min =", min(l)
#print "Max =", max(l)
return min(l), max(l)
def Run_2():
l1 = list(l)
l1.sort()
#print "Min =", l1[0]
#print "Max =", l1[-1]
return l1[0], l1[-1]
def Run_3():
minimum = float('inf')
maximum = float('-inf')
for item in l:
if item < minimum:
minimum = item
if item > maximum:
maximum = item
#print "Min =", minimum
#print "Max =", maximum
return minimum, maximum
if __name__ == '__main__':
num_runs = 10000
print "Run 1"
run1 = timeit.Timer(Run_1)
time_run1 = run1.repeat(3, num_runs)
print ""
print "Run 2"
run2 = timeit.Timer(Run_2)
time_run2 = run2.repeat(3,num_runs)
print ""
print "Run 3"
run3 = timeit.Timer(Run_3)
time_run3 = run3.repeat(3,num_runs)
print ""
print "Run 1"
for each_time in time_run1:
print "time =", each_time
print ""
print "Run 2"
for each_time in time_run2:
print "time =", each_time
print ""
print "Run 3"
for each_time in time_run3:
print "time =", each_time
print ""
我的結果是:
Run 1
time = 3.42100585452
time = 3.39309908229
time = 3.47903182233
Run 2
time = 26.5261287922
time = 26.2023346397
time = 26.7324208568
Run 3
time = 3.29800945144
time = 3.25067545773
time = 3.29783778232
排序算法對大型陣列很慢。
您需要使用'timeit'模塊來消除方差(CPU調度,交換等);它也會爲您的平臺選擇正確的計時器(最準確的選項)。 –
而一個簡單的循環是O(n)的複雜度,排序是O(n log n);這可能是因爲python for循環的不變成本高於排序的C代碼常量成本,這就是爲什麼排序後短列表可能會更快,但對於大列表循環會贏,給定足夠大的名單。 –
最後一個數據點:使用一個正確的隨機列表來測試sort()對一個循環或者min()和max()調用;排序算法(TimSort)針對部分排序的數據進行了優化;你的輸入樣本大多是排序的(只有'3'不在位)。 –
如果您試圖避免使用兩個循環,希望單個循環會更快,您需要重新考慮。調用兩個O(N)函數仍然給你一個O(N)算法,你所做的只是每迭代次數不變的兩倍。比較的單個Python循環無法比O(N)做得更好(除非您的數據已經排序),並且每次迭代的字節碼解釋也具有相當大的不變成本。哪種方法具有較高的恆定成本只能通過定時運行來確定。
要在單個循環中執行此操作,請迭代列表並按照目前發現的最小值和最大值對每個項目進行測試。 float('inf')
和float('-inf')
(無窮大和負無窮大)是很好的出發點,以簡化的邏輯:
minimum = float('inf')
maximum = float('-inf')
for item in l:
if item < minimum:
minimum = item
if item > maximum:
maximum = item
或者,啓動與在所述其餘部分的第一元件和僅循環。打開表到迭代第一,第一個元素存儲作爲結果最新,然後遍歷其餘部分:
iterl = iter(l)
minimum = maximum = next(iterl)
for item in iterl:
if item < minimum:
minimum = item
if item > maximum:
maximum = item
不要使用排序。 Python的Tim Sort實現是一個O(N log N)算法,可以預期它比直接的O(N)方法慢。
具有較大的,隨機列表時機比較:
>>> from random import shuffle
>>> l = list(range(1000))
>>> shuffle(l)
>>> from timeit import timeit
>>> def straight_min_max(l):
... return min(l), max(l)
...
>>> def sorted_min_max(l):
... s = sorted(l)
... return s[0], s[-1]
...
>>> def looping(l):
... l = iter(l)
... min = max = next(l)
... for i in l:
... if i < min: min = i
... if i > max: max = i
... return min, max
...
>>> timeit('f(l)', 'from __main__ import straight_min_max as f, l', number=10000)
0.5266690254211426
>>> timeit('f(l)', 'from __main__ import sorted_min_max as f, l', number=10000)
2.162343978881836
>>> timeit('f(l)', 'from __main__ import looping as f, l', number=10000)
1.1799919605255127
所以即使是1000元的名單中,min()
和max()
功能是最快的。排序在這裏最慢。如果允許就地排列,排序版本可以更快,但是隨後您也需要爲每個定時運行生成新的隨機列表。
遷移到萬件(每定時運行僅10個測試),我們可以看到:
>>> l = list(range(1000000))
>>> shuffle(l)
>>> timeit('f(l)', 'from __main__ import straight_min_max as f, l', number=10)
1.6176080703735352
>>> timeit('f(l)', 'from __main__ import sorted_min_max as f, l', number=10)
6.310506105422974
>>> timeit('f(l)', 'from __main__ import looping as f, l', number=10)
1.7502741813659668
最後但並非最不重要的,使用萬件和l.sort()
,而不是sorted()
:
>>> def sort_min_max(l):
... l.sort()
... return l[0], l[-1]
...
>>> timeit('f(l[:])', 'from __main__ import straight_min_max as f, l', number=10)
1.8858389854431152
>>> timeit('f(l[:])', 'from __main__ import sort_min_max as f, l', number=10)
8.408858060836792
>>> timeit('f(l[:])', 'from __main__ import looping as f, l', number=10)
2.003532886505127
請注意l[:]
;我們給每個測試運行一份清單的副本。結論:即使對於大型列表,最好使用min()
和max()
函數,但很難打敗良好C循環的低每次迭代成本。但是如果你不得不放棄這些功能,直線循環是下一個更好的選擇。
你應該更好地給他提示,而不是給他答案,stackoverflow不是爲學生做作業! :-s(儘管你使用float的'inf'的想法很整潔;-)) – zmo
不,Stack Overflow用於回答問題。 OP從來沒有要求提示,我們不是在這裏警察的作業政策。如果我是教授,如果將其作爲家庭作業答案發布,以瞭解學生是否瞭解其確切* *,我*會在答案中詢問有關代碼的尖銳問題。 –
在這種情況下,我會使用'iterable = iter(l); minimum = maximum = next(iterable)'「pattern」。它具有額外的優點,即它可以處理每個序列,而'l [0]'僅適用於索引序列。 – Bakuriu
怪異限制家庭作業問題,要求回答作弊
>>> l = [1,2,3,4,5]
>>> sorted(l)[::len(l)-1]
[1, 5]
>>> L = [1,2,3,4,5]
>>> reduce(lambda x, y: x if x<y else y, L)
1
>>> reduce(lambda x, y: x if x>y else y, L)
5
另一種方式
>>> it = iter(L)
>>> mn = mx = next(it)
>>> for i in it:
... if i<mn:mn=i
... if i>mx:mx=i
...
>>> mn
1
>>> mx
5
如果你只需要一個通過列表循環,您可以使用一個reduce
(不那麼)創造性的方式。助手功能可能已經降低拉姆達,但我不這樣做是爲了便於閱讀的緣故
>>> def f(solutions, item):
... return (item if item < solutions[0] else solutions[0],
... item if item > solutions[1] else solutions[1])
...
>>> L = [i for i in range(5)]
>>> functools.reduce(f, L, (L[0],L[0]))
(0, 4)
爲了找到最大:
print reduce(lambda x,y: x if x>y else y, map(int,raw_input().split()))
爲了找到分鐘:
print reduce(lambda x,y: x if x<y else y, map(int,raw_input().split()))
- 1. 我怎樣才能獲得列表框
- 2. 怎樣才能可以使陣列的陣列中的蟒蛇
- 3. 怎樣才能獲得一個列表?
- 4. 我怎樣才能獲得的價值總和的陣列內
- 5. 在蟒蛇,我怎樣才能得到我的正則表達式多少組獲得
- 6. 我怎樣才能得到最小的行
- 7. 我怎樣才能得到
- 8. 我怎樣才能獲得值「111」
- 9. 我怎樣才能獲得actionName在ActionFilter
- 10. 我怎樣才能獲得訪問Android
- 11. 我怎樣才能獲得R中
- 12. 我怎樣才能獲得價值? Odoo
- 13. 我怎樣才能獲得文本QTableWidgetItem
- 14. 我怎樣才能在kivy蟒蛇重新加載圖像
- 15. 我怎樣才能從手機上獲得聯繫人列表?
- 16. 我怎樣才能獲得一個SSAS Cube的dimentions和dimentions'屬性的列表
- 17. 我怎樣才能獲得最大的價值?
- 18. 我怎樣才能得到我點擊的列表項數據?
- 19. 我怎樣才能得到我的追加()列表,回來? jQuery
- 20. 我怎樣才能在巨蟒
- 21. 我怎樣才能在巨蟒
- 22. 我怎樣才能獲得無形列Telerik的網格MVC3
- 23. 我怎樣才能獲得MySQL表中的行數與PHP?
- 24. 我怎樣才能獲得和在javascript替換這個(jQuery的
- 25. Sharepoint。我怎樣才能得到列表項的「新」標誌?
- 26. 我怎樣才能得到一個類的實例列表
- 27. 我怎樣才能得到在Android的
- 28. 我怎樣才能得到Queryable.Join的MethodInfo
- 29. 我怎樣才能長雙的小區?
- 30. 我怎樣才能在mysql中獲得最高分數datewise
有沒有使用最小和最大的有效理由? – abhishekgarg
你能告訴你爲什麼不想用'min(l)'/'max(l)'?因爲如果我在這裏回答你的問題,我會給你一個非常接近min()和max()已經完成的算法。 – zmo