Python 如何利用随机轴解决R选择问题
我需要在输入列表中找到第k个数字。请告诉我怎么了Python 如何利用随机轴解决R选择问题,python,list,sorting,select,pivot,Python,List,Sorting,Select,Pivot,我需要在输入列表中找到第k个数字。请告诉我怎么了 def分区(arr、开始、结束、枢轴): pivot\u locate=arr.index(pivot) arr[pivot\u locate],arr[start]=arr[start],arr[pivot\u locate] L=启动;R=结束 i=L+1;j=L+1 对于范围(j,R+1)中的k:#k=1~R 如果arr[k]
def分区(arr、开始、结束、枢轴):
pivot\u locate=arr.index(pivot)
arr[pivot\u locate],arr[start]=arr[start],arr[pivot\u locate]
L=启动;R=结束
i=L+1;j=L+1
对于范围(j,R+1)中的k:#k=1~R
如果arr[k]<枢轴:
arr[i],arr[k]=arr[k],arr[i]
i+=1
j=k
arr[L],arr[i-1]=arr[i-1],arr[L]
返回arr
def R选择(arr、开始、结束、i):
如果start==end:返回arr[start]
如果开始<结束:
枢轴=随机选择(arr)
当arr.index(pivot)<开始或arr.index(pivot)>结束时:
枢轴=随机选择(arr)
arr_new=分区(arr、start、end、pivot)
pLoc=arr_新索引(枢轴)
如果pLoc==i:返回轴
elif pLoc>i:返回RSelect(arr_new,start,pLoc-1,i)
否则:返回RSelect(arr_new,pLoc+1,end,i)
T=int(输入())
对于范围(T)内的j:
N、 k=map(int,input().split())
我的列表=列表(映射(int,input().split())
k=len(我的列表)-k
anw=r选择(我的列表,0,len(我的列表)-1,k)
打印(anw)
有些测试代码工作正常,但有些输出的答案不正确。我不知道有什么问题。我正在学习概率选择算法。当输入列表包含大量重复值时,会出现一些问题。这些问题都与如何使用
index()
有关。您不能假设index()
将返回范围[start,end]
内搜索值的索引,即使您知道它应该在该范围内,也可能发生在该范围之外。当index()
返回第一次出现的索引时,您会得到不想要的结果:
- 在
中,分区
可能返回一个小于arr.index(pivot)
的索引,这显然会导致start
处的值被不希望的交换到范围之外start
可能为真,即使该值也存在于正在考虑的子范围中。如果范围仅包含该值的重复,而不包含其他值,则这将使该而arr.index(pivot)
循环成为无限循环
也会出现类似的问题。这可能导致递归调用,其中范围大于当前范围,从而导致潜在的堆栈溢出arr\u new.index(pivot)
arr\u new=partition()。因此,为了避免误解,最好继续使用
,而不要为同一列表引入新变量。与其返回arr
,不如使用arr
返回轴心值结束位置的索引。这样,您就不必再执行partition
调用了index
必须搜索给定的轴值。它可以通过传递枢轴的索引从该扫描中释放出来。您应该真正避免使用分区
,因为它会导致更糟糕的平均时间复杂度索引
def partition(arr, start, end, pivot_locate):
# The function gets the index, and now gets the pivot value
pivot = arr[pivot_locate]
arr[pivot_locate], arr[start] = arr[start], arr[pivot_locate]
L = start; R = end
i = L+1; j = L+1
for k in range(j, R+1):
if arr[k] < pivot:
arr[i], arr[k] = arr[k], arr[i]
i += 1
j = k
arr[L], arr[i-1] = arr[i-1], arr[L]
return i-1 # return the new index of the pivot
def RSelect(arr, start, end, i):
if start >= end:
return arr[start]
if start < end:
# Select a random index within the range
pLoc = random.randint(start, end)
# call partition with that index and get a new index back
pLoc = partition(arr, start, end, pLoc)
if pLoc == i:
return arr[pLoc]
elif pLoc > i:
return RSelect(arr, start, pLoc-1, i)
else:
return RSelect(arr, pLoc+1, end, i)
def分区(arr、start、end、pivot\u-locate):
#函数获取索引,现在获取轴值
枢轴=arr[枢轴位置]
arr[pivot\u locate],arr[start]=arr[start],arr[pivot\u locate]
L=启动;R=结束
i=L+1;j=L+1
对于范围(j,R+1)内的k:
如果arr[k]<枢轴:
arr[i],arr[k]=arr[k],arr[i]
i+=1
j=k
arr[L],arr[i-1]=arr[i-1],arr[L]
返回i-1#返回枢轴的新索引
def R选择(arr、开始、结束、i):
如果开始>=结束:
返回arr[开始]
如果开始<结束:
#选择范围内的随机索引
pLoc=random.randint(开始、结束)
#使用该索引调用分区并获取新索引
pLoc=分区(arr、开始、结束、pLoc)
如果pLoc==i:
返回arr[pLoc]
elif pLoc>i:
返回RSelect(arr、start、pLoc-1、i)
其他:
返回RSelect(arr、pLoc+1、end、i)
def partition(arr, start, end, pivot_locate):
# The function gets the index, and now gets the pivot value
pivot = arr[pivot_locate]
arr[pivot_locate], arr[start] = arr[start], arr[pivot_locate]
L = start; R = end
i = L+1; j = L+1
for k in range(j, R+1):
if arr[k] < pivot:
arr[i], arr[k] = arr[k], arr[i]
i += 1
j = k
arr[L], arr[i-1] = arr[i-1], arr[L]
return i-1 # return the new index of the pivot
def RSelect(arr, start, end, i):
if start >= end:
return arr[start]
if start < end:
# Select a random index within the range
pLoc = random.randint(start, end)
# call partition with that index and get a new index back
pLoc = partition(arr, start, end, pLoc)
if pLoc == i:
return arr[pLoc]
elif pLoc > i:
return RSelect(arr, start, pLoc-1, i)
else:
return RSelect(arr, pLoc+1, end, i)