2021.11.18-2021.11.22
Datawhale 11月学习内容;学习地址:https://algo.itcharge.cn/
本篇内容:精炼笔记+难点自己注解+习题多种解法
文章目录
1. 排序
1.1 冒泡排序
思想:
- 就是两层循环
- 每层循环将一个最大的排到最后
- 不断缩小排序范围 直到所有都排完。
特点:
- 稳定排序法
- 平均时间复杂度 O ( n 2 ) O(n^2) O(n2)
def bubbleSort(arr):
for i in range(len(arr)):
for j in range(len(arr)-i+1)):
if arr[j] > arr[j+1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
1.2 选择排序
思想:
- 用一个变量记录最小的位置
- 开始假设0号位是最小,那么遍历一遍,找到最小位置与0号交换位置
- 第二轮从1号位开始找最小,直到所有都找一遍
特点:
- 其选择排序的最好、最坏、平均情况下复杂度都是 O ( n 2 ) O(n^2) O(n2)
- 选择排序不是稳定性排序。举个例子:数组【6】、7、6、2、8 排序后 2、6、【6】、7、8
def selectSort(arr):
for i in range(len(arr)-1):
min_i = i
for j in range(i+1, len(arr)):
if arr[j] < arr[min_i]:
min_i = j
#如果找到最小数,将 i 位置上元素与最小数位置上元素进行交换
if i != min_i:
arr[i], arr[min_i] = arr[min_i], arr[i]
return arr
注意:
- 2个数时,只需要比较1次就可确定本轮最小值,3个数比较2次。
i
是比较的次数(第几轮)所以末端在len(arr)-1
;
-j
则是比较数的位置,所以末端在len(arr)
1.3 插入排序
思想:
- 前面是已经排好的从小到大的顺序
- 我们从后面取一根新的,逐一向前比较,插入新的位置,是前面依旧有序
特点:
- 稳定排序法
- 最差情况是都是逆序,最好情况都是顺序,平均时间复杂度 O ( n 2 ) O(n^2) O(n2)
def insertionSort(arr):
for i in range(1, len(arr)):
temp = arr[i]
j = i
while j > 0 and arr[j - 1] > temp:
arr[j] = arr[j - 1]
j -= 1
arr[j] = temp
return arr
另一种写法:
def insertSort(arr):
size = len(arr)
# 一共要循环n次,i来索引新的
for i in range(size):
insert_i = i
# 拿到一个元素 和所有后面的比较 找出最小的
for j in range(i,0,-1):
if arr[j] < arr[j-1]:
arr[j-1], arr[j] = arr[j], arr[j-1]
return arr
range(i,0,-1)
这个还是左闭右开,所以没有0,倒序,也就是从i
开始 一直到1
1.4 希尔排序
思想:
- i是从一个gap以外开始的,0-i之间使我们要排的范围
for i in range(gap,size)
- 我们做的就是每隔一个gap保证是有序的。方法类似于冒泡,用
j
与j-n*gap
比较大小,让新进入的i落入到应该有的位置while j>=gap and arr[j - gap] > temp:
特点:
- 希尔排序方法的排序总躺数为 l o g 2 n log_2n log2n 。中间层 do-while 循环为
n
数量级。当子序列分得越多时,子序列内的元素就越少,最内层的 for 循环的次数也就越少;反之,当所分的子序列个数减少时,子序列内的元素也随之增多,但整个序列也逐步接近有序,而循环次数却不会随之增加。因此,希尔排序算法的时间复杂度在 O ( n 2 ) O(n^2) O(n2) 与 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n) 之间。 - 是一种不稳定排序算法
def shellSort(arr):
size = len(arr)
gap = size // 2
while gap > 0:
for i in range(gap, size):
temp = arr[i]
j = i
while j >= gap and arr[j - gap] > temp:
arr[j] = arr[j - gap]
j -= gap
arr[j] = temp
gap = gap // 2
return arr
另一种写法:直接新进来的 与相对于的数比较 交换就行了
def shellSort(arr):
size = len(arr)
gap = size // 2
while gap > 0:
for i in range(gap, size):
# 这里面可以不用j,全部用i 我这里为了方便理解
j=i
while j >= gap and arr[j-gap] > arr[j]:
# 用新进来较小的 和前面比他大的不断交换位置
arr[j-gap], arr[j] = arr[j], arr[j-gap]
j = j-gap
gap = gap // 2
return arr
1.5 归并排序
思想:
- 先小范围排序,不断扩排序范围
- (2), (2), (2), (2),排
- (2, 2), (2, 2) 排
- (2, 2,2, 2) 排
特点:
- 稳定排序算法
- 归并排序算法的时间复杂度等于归并趟数与每一趟归并的时间复杂度成绩。子算法
merge(left_arr, right_arr)
的时间复杂度是 O ( n ) O(n) O(n),因此,归并排序算法总的时间复杂度为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)
def merge(left_arr, right_arr):
arr = []
whiel left-arr or right_arr:
if left-arr[0] <= right_arr[0]:
arr.append(left_arr.pop(0))
else:
arr.append(right_arr.pop(0))
while left_arr:
arr.append(left_arr.pop(0))
while right_arr:
arr.append(right_arr.pop(0))
return arr
def mergeSort(arr):
size = len(arr)
if size < 2:
return arr
mid =