问题1:荷兰国旗问题
给定一个数组arr,和一个数num,请把小于num的数放在数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边。
要求额外空间复杂度O(1),时间复杂度O(N)
import random
def netherlands_flag(arr, l, r, num):
less = l - 1 # 便于理解
more = r + 1
while l < more:
if arr[l] < num:
less += 1
arr[less], arr[l] = arr[l], arr[less]
l += 1
elif arr[l] > num: # 拿过来的数据待定,则不能l+=1
more -= 1
arr[more], arr[l] = arr[l], arr[more]
else:
l += 1
return (less+1, more-1) # 返回num的区域下标
def generate_arr(size):
arr = []
for i in range(size):
arr.append(int(random.random() * 3)) # [0-2]
return arr
arr = generate_arr(10)
num_index = netherlands_flag(arr, l=0, r=len(arr) - 1, num=1)
print(arr)
print(num_index)
二、随机快排细节和复杂度分析
- partition 不均问题,或者当为有序数组时,经典快排容易出现 O(n^2)。经典快排空间复杂度最坏为 O(N),最好为 O(logN)
- 随机快排的 (长期期望) 时间复杂度为 O(N*logN),(最常用的排序算法,实现简单,常数项少, 空间复杂度低),额外 (长期期望) 空间复杂度 O(logN)
- 工程中一般不会使用递归函数,递归都能改成非递归。系统压栈会有过多无用常数项
import random
def quick_sort(arr, l, r):
if l < r:
# 随机获取[l:r]某个数, 这里l不能少,不然递归出问题
r_num = l + int(random.random() * (r - l + 1))
arr[r_num], arr[r] = arr[r], arr[r_num]
p = netherlands_flag(arr, l, r) # p为中位数的前后位置元祖
quick_sort(arr, l, p[0] -1)
quick_sort(arr, p[1] + 1, r)
def netherlands_flag(arr, l, r):
less = l - 1
more = r # 这里r为中位数,不参与比较,最后需要置换
while l < more:
if arr[l] < arr[r]:
less += 1
arr[less], arr[l] = arr[l], arr[less]
l += 1
elif arr[l] > arr[r]:
more -= 1
arr[more], arr[l] = arr[l], arr[more]
else:
l += 1
arr[more], arr[r] = arr[r], arr[more]
return [less+1, more]
def generate_arr(size):
arr = []
for i in range(size):
arr.append(int(random.random() * 10)) # [0-10]
return arr
arr = generate_arr(10)
print(f'old arr: {arr}')
quick_sort(arr, l=0, r=len(arr) - 1) # [3, 6, 5, 8, 4]
print(f'sort arr: {arr}')
堆排序的细节和复杂度分析
完全二叉树(堆 --> 完全二叉树
),叶节点概念
i节点
:左 2i + 1,右 2i + 2,父 int((i - 1)/2)
,int() 保证出现 -1/2 为0
- 大根堆:完全二叉树中每一颗头节点都为最大值
- 小根堆:完全二叉树中子节点为最小值
- heapinsert:新的节点加入,重新生成大跟堆
- heapify:节点发送变化,重新生成大根堆
流数据求中位数
:准备大根堆和小根堆,保证两边数据相差不超过1,中位数就是两个表头之一。
堆排序Code
# 时间复杂度O(N*logN),额外空间复杂度O(1)
def code_02_heap_sort():
def heap_sort(arr):
if arr == [] or len(arr) <2:
return arr
for i in range(len(arr)):
heap_insert(arr, i)
size = len(arr) - 1
arr[0], arr[size] = arr[size], arr[0]
while size > 0:
heapify(arr, 0, size)
size -= 1
arr[0], arr[size] = arr[size], arr[0]
def heap_insert(arr, index):
parent_node = int((index - 1) / 2)
while arr[index] > arr[parent_node]:
arr[index], arr[parent_node] = arr[parent_node], arr[index]
index = parent_node
parent_node = int((index - 1) / 2)
def heapify(arr, index, size):
left_node = index*2 + 1
while left_node < size:
largest = left_node+1 if left_node + 1 < size and arr[left_node+1] > arr[left_node] else left_node
largest = largest if arr[largest] > arr[index] else index
if largest == index:
break
arr[index], arr[largest] = arr[largest], arr[index]
index = largest
left_node = index*2 + 1
arr = [3,1,2,6,0,4] # 这里可以使用对数器,解决样本问题
heap_sort(arr)
print(arr)
code_02_heap_sort()