Merge Sort. $O(1),O(N\log N) $

4 篇文章 0 订阅
2 篇文章 0 订阅

归并排序

Tips:
1. a = b + c*2**k
2. b =  a % c =   a & (k-1)
3. c =  a // 2**k = a >> k
For example:
1.  643 = 3 + 20*2**5
2.  3 = 643 % 32 = 643 & 31
3.  20 = 643 // 32 = 643 >> 5
import math
from typing import List


def getPower2(n: int):
    """Returns a power of two size for the given target n.
    max is 2**32
    Tips:
        keep moving to the right to make all the bits 1
        From JDK1.8 HashTable.
    """
    if n < 2:
        raise Exception("the number must be greater than 1.")
    n -= 1
    n |= n >> 1
    n |= n >> 2
    n |= n >> 4
    n |= n >> 8
    n |= n >> 16
    return (n+1, int(math.log2(n+1)))


def merge_sort(arr: List[int]):
    """Divide and conquer algorithm.
    Complexity:
        Time: $O(n\logn)$
        Space: $O(1)$
        Stable: yes
    Example:
    >>> raw_data = [0, 10, 15, 9, 3, 13, 21, 6, 8, 10]
    >>> merge_sort(raw_data)
    [0, 3, 6, 8, 9, 10, 10, 13, 15, 21]
    >>> raw_data
    [0, 10, 15, 9, 3, 13, 21, 6, 8, 10]
    """
    # Copy arr, don't change raw data.
    arr = arr[:]
    max_num, power = getPower2(max(arr)+1)

    def merge(left, mid, right):
        """Once merge
        """
        i, j, k = left, mid + 1, left
        while i <= mid and j <= right:
            # Compare
            a = arr[i] & (max_num - 1)
            b = arr[j] & (max_num-1)
            if a < b:
                arr[k] = arr[k] + a * max_num
                i += 1
            else:
                arr[k] = arr[k] + b * max_num
                j += 1
            k += 1
        # Checking if any elements was left
        while i <= mid:
            arr[k] = arr[k] + (arr[i] & (max_num - 1)) * max_num
            i += 1
            k += 1
        while j <= right:
            arr[k] = arr[k] + (arr[j] & (max_num - 1)) * max_num
            j += 1
            k += 1
        # Restore
        for i in range(left, right + 1):
            arr[i] >>= power

    def merge_sort_rec(left, right):
        # recurse return point.
        if left >= right:
            return
        mid = (left + right) >> 1
        # Divide
        merge_sort_rec(left, mid)
        merge_sort_rec(mid+1, right)
        merge(left, mid, right)

    merge_sort_rec(0, len(arr) - 1)
    return arr


if __name__ == "__main__":
    import doctest
    doctest.testmod(verbose=True)

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值