Python 如何利用随机轴解决R选择问题

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]

我需要在输入列表中找到第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)