剑指offer之029-最小的K个数

题目描述

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

思路

思路1:

  • 最小堆建立(需要o(n)时间复杂度)
  • 取出前k个数(每次取需要用logn时间重建堆)。时间复杂度为o(n)+o(k*logn)

思路2:

  • 用快排partition划分,一直划中第k个数 最差情况o(kn)
#思路1

def sink(array, k):
    n = len(array)
    left = 2 * k + 1
    right = 2 * k + 2
    if left >= n: return
    min_i = left 
    if right < n and array[left] > array[right]:
        min_i = right
    if array[min_i] < array[k]:
        array[min_i], array[k] = array[k], array[min_i]
        sink(array, min_i)

def build_heap(list):
    n = len(list)
    for i in range(n//2, -1, -1):
        sink(list, i)

    return list

def GetLeastNumbers_Solution(tinput, k):
    if k > len(tinput): return []
    heap = build_heap(tinput)  # 建堆o(n)复杂度
    res = []
    for _ in range(k):  # 取topk o(klogn)复杂度
        heap[0], heap[-1] = heap[-1], heap[0]
        res.append(heap.pop())
        sink(heap, 0)
    return res


print(GetLeastNumbers_Solution([4,5,1,6,2,7,3,8],4))
#思路2:
def partition(input, low, high):
    pivot = input[low]
    while low < high:
        while low < high and pivot <= input[high]:
            high -= 1
        input[low] = input[high]
        while low < high and pivot >= input[low]:
            low += 1
        input[high] = input[low]
    input[low] = pivot
    return low


def GetLeastNumbers_Solution(tinput, k):
    if k > len(tinput) or k <= 0: return []
    idx = partition(tinput, 0, len(tinput) - 1)
    low = 0
    high = len(tinput) - 1
    while idx != k - 1:
        if idx < k - 1:
            low = idx + 1
            idx = partition(tinput, low, high)
        if idx > k - 1:
            high = idx - 1
            idx = partition(tinput, low, high)
    return tinput[:k]


print(GetLeastNumbers_Solution([4,5,1,6,2,7,3,8],4))
print(GetLeastNumbers_Solution([-4, 2, 1, 23, 7, 2, 18, 23, 42, 37, 8], 4))

关于明柳梦少

坚守自己的原则,不随波逐流。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注