華電北風吹
天津大學認知計算與應用重點實驗室
日期:2015/7/7
一、選擇最大值或者最小值的最優演算法
對於長度為n的陣列,已證找最大值或者最小值比較操作下界就是n-1。所以只需要讓第乙個值為初始最大值或者初始最小值,用所有的值與這個值比較,更新這個值即可。
def
minimum
(a):
minnum=a[0]
for i in range(1,len(a)):
if minnum>a[i]:
minnum=a[i]
return minnum
print(minimum ([1,2,3,4,5,6,7,8,9]))
二、同時選擇最大值和最小值的快速演算法(成對比較)
首先設定一對初始的最大值最小值(總數個數是奇數,初始最大值最小值為第乙個數,若是偶數就為前兩個比較),然後剩下的數兩兩組對,對內比較大小,然後小的與當前最小的比,大的與當前最大的比。這樣的話兩個數需要比較三次。如果選擇分別計算最大值最小值需要2(n-1)次比較,採用成對比較的話只需要3int(n/2)次
def minmax(a):
k=len(a)
if k%2==0:
ifa[0]minnum,maxnum=a[0],a[1]
else:
minnum,maxnum=a[1],a[0]
else:
minnum,maxnum=a[0],a[0]
for i in range(2-k%2,k,2):
ifa[i]>a[i+1]:
a[i+1],a[i]=a[i],a[i+1]
ifa[i]a[i]
ifa[i+1]>maxnum:
maxnum=a[i+1]
return minnum,maxnum
print(minmax([1,2,3,4,5,6,7,8,9]))
三、期望時間為線性時間的選擇演算法—隨機選擇
回想一下,快速排序的時候,選擇乙個數(隨機)為基準,左右交換將小於基準的分到左邊,大於基準的分到右邊的思想,然後得到這個數在陣列中的位置,這樣我們可以根據這個位置判斷我們要的數所處的位置,逐步縮小搜尋範圍。
基於快速排序的捨棄法,不考慮直接命中的情況的話一次平均捨棄一半的數。
import random
defrandomizedpartion
(a,p,r):
k=random.randint(p, r)
a[k],a[r]=a[r],a[k]
value=a[r]
i=p-1
for j in range(p,r):
if a[j]1
a[i],a[j]=a[j],a[i]
i+=1
a[i],a[r]=a[r],a[i]
return i
defrandomizedselect
(a,p,r,i):
q=randomizedpartion(a,p,r)
k=q-p+1
if k==i:
return a[q]
else:
if ireturn randomizedselect(a,p,q-1,i)
else:
return randomizedselect(a,q+1,r,i-k)
lst=[2,6,3,1,5,0,7,8,4,9]
k=randomizedselect(lst,0,len(lst)-1,10)
print(k)
四、最壞時間為線性時間的選擇演算法—中位數的中位數劃分
select演算法的思想為:首先對陣列中所有的數分組,然後計算每個組的中位數,然後計算所有組的中位數的中位數,然後把快速排序劃分策略修改為按值劃分,並且返回中位數的中位數在陣列中位置。然後就可以判斷捨棄了。
基於中位數的中位數一次捨棄的數有下限n/4(這個是我自己算的乙個下限,下確界可能更高點)——比如要找的數小於中位數的中位數,組裡面的中位數大於中位數的中位數的那些組上半部分是肯定這一輪需要捨棄的,而這個的乙個下線就是n/4,這樣每次最多儲存上一次資料的3n/4個資料,而每一次長度為n的計算量為theta(n),根據等比數列性質,它的階數是跟首項同階的。所以最壞情況的計算時間為theta(n)。
def
midnum
(a):
k=len(a)
groupnum=5
start=0
while start1,start+4)
insertsort(a,start,end)
start+=5
if k<5:
return a[(k-1)//2]
else:
b=a[(groupnum//2)::groupnum]
return midnum(b)
definsertsort
(a,start,end):
for k in range(start+1,end+1):
i=kwhile a[i-1]>a[i] and i>start:
a[i-1],a[i]=a[i],a[i-1]
i-=1
return a
defpartionbyvalue
(a,x):
i=0j=0
for k in range(0,len(a)):
if a[k]1
for k in range(i,len(a)):
if a[k]==x:
j=ka[i],a[j]=a[j],a[i]
return i
defselect
(a,i):
mid=midnum(a)
k=partionbyvalue(a,mid)+1
if i==k:
return mid
else:
if ireturn select(a[0:k-1],i)
else:
return select(a[k::],i-k)
lst=[2,6,3,1,5,0,7,8,4,9]
k=select(lst,10)
print(k)
補充說明:
等比數列求和問題
等比數列通項公式:a(m)=a(1)*q^(m-1)
等比數列求和公式:s(m)=a(1)* ( 1-q^m ) / ( 1-q )
如果a(1)=c*n
a(m+1)=q*a(m) (q<1)
可以求的s(m)=c*n* ( 1-q^m ) / ( 1-q )=theta(n)
在此部落格中,問題三對應q=0.5,問題四對應q<0.75,所以都是線性時間演算法
批註:階數只是對特別大的資料的時候,階數越低計算時間越短,資料量小的時候,線性時間的常數比例因子比較影響效果。
演算法導論 中位數和順序統計量
在乙個由n個元素組成的集合中,第i個順序統計量是該集合中第i小的元素。乙個中位數是它所屬集合的 中點元素 當n為奇數時,中位數是唯一的,位於i n 1 2處 當n為偶數時,存在兩個中位數,分別位於i n 2和i n 2 1處。如果不考慮n的奇偶性,中位數總是出現在i n 1 2 處 下中位數 和i ...
中位數與順序統計量
在有n個元素的集合中如果想找最小值,最優也就是n 1次,但如果同時找最大值和最小值,最優可以不是2 n 1 次而是3 n 2 次,基本思路是成對的比較,先兩個數之間比較,較小值與最小值比較,較大值與最大值比較,注意奇數偶數要分開討論。include includeusing namespace st...
演算法導論之中位數和順序統計量(3)
在乙個由n個元素組成的集合中,第i個順序統計量是該集合中的第i小的元素。本章的演算法正是找出乙個互異的元素集合中的第i小的元素。單個的最小值和最大值 在乙個有n個元素的集合中,我們要確定其中最小的元素,必須要進行n 1次比較,正如minmum a 演算法顯示的這樣 minmun a min a i ...