Select. Worst-case Θ(n).

2018-05-07  本文已影响15人  R0b1n_L33

Effectively, factoring out the selectMedian function is quite usable for analysis of the algorithm by eliminating the recursive T(n/5) item.

As a result, T(n) <= T(7n/10) + Θ(n), in which Θ(n) is the expense of function partitionByPivot and function selectMedian(T(n) <= T(n/5) + Θ(n)).

So the inequality can be reduced to T(n) <= T(7n/10) + Θ(n) and result in Θ(10n/3), which is resolved by master method or reasoned out by recursion tree and geometric progression.

def swap(array:[], index1, index2):
    array[index1], array[index2] = array[index2], array[index1]

def insertSort(array:[], startIndex:int, endIndex:int):
    if startIndex >= endIndex:
        return
    for i in range(startIndex+1, endIndex+1):
        target = array[i]
        targetIndex = startIndex
        for j in reversed(range(startIndex, i)):
            if array[j] > target:
                array[j+1] = array[j]
            else:
                targetIndex = j+1
                break
        array[targetIndex] = target

def partitionByPivot(array:[], startIndex:int, endIndex:int, pivot:int) -> int:
# Θ(n).
    lastLessorIndex = startIndex - 1
    pivotIndex = -1
    for i in range(startIndex, endIndex+1):
        if array[i] <= pivot:
            lastLessorIndex += 1
            swap(array, i, lastLessorIndex)
            if array[lastLessorIndex] == pivot:
                pivotIndex = lastLessorIndex
    swap(array, pivotIndex, lastLessorIndex)
    return lastLessorIndex

def selectMedian(array:[], startIndex:int, endIndex:int) -> int:
# Θ(n).
    count = endIndex - startIndex + 1
    if count > 5:
        medians = []
        i = startIndex
        while i + 5 <= endIndex:
            insertSort(array, i, i+4)
            medians.append(array[i+2])
            i += 5
        insertSort(array, i, endIndex)
        medians.append(array[(i+endIndex)//2])
        return selectMedian(medians, 0, len(medians)-1)
    insertSort(array, startIndex, endIndex)
    return array[(startIndex+endIndex)//2]

def select(array:[], startIndex:int, endIndex:int, targetOrder:int) -> int:
    if startIndex == endIndex:
        return array[startIndex]
    pivot = selectMedian(array, startIndex, endIndex)
    pivotIndex = partitionByPivot(array, startIndex, endIndex, pivot)
    targetIndex = startIndex + targetOrder
    if pivotIndex == targetIndex:
        return pivot
    elif pivotIndex < targetIndex:
        return select(array, pivotIndex+1, endIndex, targetIndex-pivotIndex-1)
    else:
        return select(array, startIndex, pivotIndex-1, targetOrder)

上一篇下一篇

猜你喜欢

热点阅读