排列顺序中数组中的k个最小值

时间:2019-04-02 08:10:35

标签: python

给定一个大小为n的数组,问题是要按排序顺序返回前k个最小的元素。 我的想法是更新QuickSort算法,首先找到第一个k元素,然后递归更新问题以找到k-1个最大元素。 找不到我的错误在哪里。

    def partition(a, left, right):
      pivot = a[left]
      p = left
      q = right
      while(p < q):
        while(a[q] > pivot and p < q):
          q-=1
        while(a[p] <= pivot and p < q):
          p+=1
        a[p] , a[q] = a[q] , a[p]
      a[left],a[p]=a[p],a[left]
      return p


    def kthSmallest(a, left, right, k,c=0):
      if left>=right:
        return a[c:]
      else:
        curr = partition(a, left, right)
        if curr - left == k - 1:
          return kthSmallest(a, left,curr-left-1,k-1,c+1)
        if(curr - left > k - 1):
          return kthSmallest(a, left, curr-1, k,c)
        return kthSmallest(a, curr+1, right, k - (curr - left + 1),c)

temp=[8,5,2,1,6,7,4,9,0]

print(kthSmallest(a,0,len(temp)-1,2))

2 个答案:

答案 0 :(得分:1)

您的递归对我来说真的没有任何意义。大多数情况下,您应该遵循快速排序的常规算法,可以避免对数组中不需要的部分进行排序(保证值超过第k个)。

这就是我要做的。您始终在左侧分区上进行递归,如果枢轴索引curr小于k,则始终在右侧分区上递归。如果curr较大,则可以跳过第二次递归,因为我们不需要任何这些值。我将切片分割为一个非递归函数,因此我们不需要在每个递归调用中都这样做。

def partial_sort(a, left, right, k):
  if left >= right: # base case, do nothing
    return
  curr = partition(a, left, right)
  partial_sort(a, left, curr-1)  # always recurse on the left partition
  if curr < k:     # we only sometimes need to recurse twice
    partial_sort(a, curr+1, right)

def kthSmallest(a, k):
  partial_sort(a, 0, len(a)-1, k)
  return a[:k]

我还想指出,有一种稍微有效的算法来解决这种精确的计算,并且它在Python标准库中有一个实现。 heapq.nsmallest函数使用二进制最大堆来非常优雅地解决此问题。我强烈建议checking it out

答案 1 :(得分:-1)

如果我对您的问题正确,则可以使用:

 min_k_values = np.sort(x, axis = None)[:k]