递归算法
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)