python_5_递归+归并排序+快速排序

递归算法

1 二分法求数组最大值

在这里插入图片描述
这可以直接确定复杂度
N\b是子问题复杂度规模,子问题规模要一致
master公式
在这里插入图片描述
对于上面那个问题

 mid = (L + R) / 2

左右都会砍一半,也就是子问题是一半 ,所以 N/b = N/2

def poress(arr,L,R):
    if L == R:
        return arr[L]
    mid = (L + R) / 2
    leftMax = poress(arr,L,mid)
    rightMax = poress(arr,mid,R)
    return Math.max(leftMax,,rightMax)

除了那两句递归之外剩下的时间复杂度,剩下是常数项,所以d=0

2 哈希表

最强功能,进行增删改查,在使用时一律为O(1).
在这里插入图片描述
字典实现哈希表基本使用:https://blog.csdn.net/wycgi/article/details/85063342

有序表

3 归并排序

在这里插入图片描述
在这里插入图片描述

def poress(arr,L,R):
    if L == R:
        return
    mid = (L + R) / 2
    poress(arr,L,mid)      # 左部分排好序
    poress(arr,mid,R)     # 右部分排好序
    merge(arr,L,mid,R)

def merge(arr,L,M,R):   # 归并排序
    help = []           # 准备新数组
    i = 0               # i在0位
    p1 = L              # p1指向左边第一个数
    p2 = M + 1          # p2指向右边的第一个数
    while p1 <= M and p2 <= R:   # p1和p2都不越界时
        if arr[p1] <= arr[p2]:
            help[i] = arr[p1]     # 新数组
            p1 += 1
        else:
            help[i] = arr[p2]
            p2 += 1
        i += 1

    while p1 <= M:      # 如果其中一个没有越界,说明还有剩余的数没有放到数组内
        help[i] = arr[p1]
        i = i + 1
    while p2 <= R:
        help[i] = arr[p2]
        i = i + 1
    for i in range(len(help)):
        arr[L + i] = help[i]

递归调用过程
在这里插入图片描述
不递归方式

import math
def mergeSort(arr):
    if arr == None or len(arr) < 2:
        return
    N = len(arr)              # N是数组长度
    mergeSize = 1             # 当前有序的,左组长度,【1,2,3,4,5】,mergeSize=1 ,1为左组,2为右组
    while mergeSize < N:      # mergeSize长度小于数组长度
        L = 0                 # 左组开始位置,L是记录第一个左组在哪开始,第二个左组在哪开始
        while L < N:
            # 左组大小为mergeSize,大小知道,可以得到L...M的范围,M是中点
            M = L + mergeSize - 1
            if M >= N:         # 凑不出左组个数了,剩下凑不齐的已经有序了
                break
            R = math.min(M + mergeSize,N - 1)     # 找右边界,如果剩下数据够右组就M + mergeSize,不够右组就N-1
            merge(arr,L,M,R)    # 左组右组找到后,归并排序
            L = R + 1           # 下一组左组位置未R+1
        if mergeSize > N / 2:   # 防溢出
            break
        mergeSize = mergeSize * 2

def merge(arr,L,M,R):   # 归并排序
    help = []           # 准备新数组
    i = 0               # i在0位
    p1 = L              # p1指向左边第一个数
    p2 = M + 1          # p2指向右边的第一个数
    while p1 <= M and p2 <= R:   # p1和p2都不越界时
        if arr[p1] <= arr[p2]:
            help[i] = arr[p1]     # 新数组
            p1 += 1
        else:
            help[i] = arr[p2]
            p2 += 1
        i += 1

    while p1 <= M:      # 如果其中一个没有越界,说明还有剩余的数没有放到数组内
        help[i] = arr[p1]
        i = i + 1
    while p2 <= R:
        help[i] = arr[p2]
        i = i + 1
    for i in range(len(help)):
        arr[L + i] = help[i]

3.1 归并排序题目

在这里插入图片描述

import math
# arr[0...R]既要排好序,也要求小和返回
# 所有merge时,产生的小和,累加
# 左排序 merge
# 右排序 merge
# merge

def process(arr,l,r):
    if l == r:
        return 0
    mid = (l + r) / 2
    return process(arr,l,mid)+process(arr,mid+1,r)+merge(arr,l,mid,r)


def merge(arr,L,M,R,r):   # 归并排序
    help = []           # 准备新数组
    i = 0               # i在0位
    p1 = L              # p1指向左边第一个数
    p2 = M + 1          # p2指向右边的第一个数
    res = 0             # 记录小和
    while p1 <= M and p2 <= R:   # p1和p2都不越界时
        if arr[p1] < arr[p2]:
            res = res + (r - p2 + 1) * arr[p1]   # (r - p2 + 1)右边有几个比他大
            help[i] = arr[p1]     # 新数组
            p1 += 1
        else:
            help[i] = arr[p2]
            p2 += 1
        i += 1

    while p1 <= M:      # 如果其中一个没有越界,说明还有剩余的数没有放到数组内
        help[i] = arr[p1]
        i = i + 1
    while p2 <= R:
        help[i] = arr[p2]
        i = i + 1
    for i in range(len(help)):
        arr[L + i] = help[i]
    return res

4 随机排序

在这里插入图片描述

def swap(arr,i,j):
    tmp = arr[i]
    arr[i] = arr[j]
    arr[j] = tmp

# 在arr数组中的L--R位置上进行排序,以arr[R]做划分值
# <arr[R]  =arr[R]  >arr[R]
def partition(arr,L,R):
    if L > R:
        return -1
    if L == R:
        return L
    lessEqual = L - 1   # 小于区域右边界
    index = L
    while index < R:
        if arr[index] <= arr[R]:
            lessEqual = lessEqual + 1
            swap(arr,index,lessEqual)
        index = index + 1
    lessEqual = lessEqual + 1
    swap(arr,lessEqual,R)
    return lessEqual

多加了一个等于区的条件
在这里插入图片描述
上面这张图与下面的区别是,下面大于区域包括了右边第一个数,因为默认将右边第一个数做比较数

4.1 荷兰国旗问题

def swap(arr, i, j):
    tmp = arr[i]
    arr[i] = arr[j]
    arr[j] = tmp


# 荷兰国旗问题
def partition(arr, L, R):
    if L > R:
        return [-1,-1]
    if L == R:
        return [L,R]
    less = L - 1  # 小于区域右边界,不包括左边第一个数
    more = R      # 大于区域左边界,[6],more = 6,包括了右边第一个数,要固定右边第一个数
    index = L     # 左边第一个数
    while index < more:             # 左右两个指针没有相遇时
        if arr[index] == arr[R]:           # 以arr[R]作分割
            index = index + 1
        elif arr[index] < arr[R]:
            less = less + 1  # 小于区域向右扩一个位置
            swap(arr, index, less)  # 把小值和小于区域的数交换
            index = index + 1  # index移动到下一个
        else:                  # 第一次,如果右边第一个数大于左边
            more = more - 1    # 大于区域向左扩一个位置,more = 5,先将R[6]固定在最后一个位置上
            swap(arr, index, more)        # R[5] 与 左边第一个数交换,将R[6]数固定在最后一个位置上
    swap(arr, more, R)         # 将大于区域的第一个数和R(固定的数)位置上交换,接触R位置固定
    return [less+1,more]                  # 返回等于区域的位置,返回大小为2的数组,第一个数是等于区域最左边的数,第二个数是等于区域最右边的数

5 快速排序v1.0

在这里插入图片描述

def quickSort1(arr):        # 快速排序v1.0
    if arr == None or len(arr) < 2:
        return 
    process1(arr,0,len(arr) - 1)
    
def process1(arr,L,R):
    if L >= R:
        return
    # <arr[R]       =arr[R] 这个数已经确定位置了        >arr[R]
    M = partition(arr,L,R)       # M接受的是确定了的中间数
    process1(arr,L,M - 1)
    process1(arr,M + 1,R)

6 快速排序v2.0

def quickSort2(arr):        # 快速排序v2.0
    if arr == None or len(arr) < 2:
        return
    process2(arr,0,len(arr) - 1)

def process2(arr,L,R):      # 默认以arr[R] 做划分
    if L >= R:
        return
    equalArea = partition(arr,L,R)  # equalArea接受的是中间数的位置
    process2(arr,L,equalArea[0] - 1)  # equalArea[0] - 1 是小于区域的最后一个数
    process2(arr,equalArea[1] + 1,R)  # equalArea[1] + 1 是大于区域的第一个数

7 快速排序v3.0

def quickSort3(arr):        # 快速排序v3.0
    if arr == None or len(arr) < 2:
        return
    process3(arr,0,len(arr) - 1)

def process3(arr,L,R):      # 默认以arr[R] 做划分
    if L >= R:
        return
    swap(arr,L + (int)(math.random() * (R - L + 1)),R)   # (int)(math.random() * (R - L + 1) 随机选一个位置,人为与R位置上的数做交换
    equalArea = partition(arr,L,R)
    process3(arr,L,equalArea[0] - 1)
    process3(arr,equalArea[1] + 1,R)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值