1. 递归
递归的特点: 调用自身 结束条件
递归的例子:汉诺塔问题
2的64次方
if n > 0:
hanoi(n-1,a,c,b)
print("moving from %s to %s" %(a,c))
hanoi(n-1,b,a,c)
hanoi(6,'A','B','C')
2.时间复杂度
定义:用来评估算法运行效率的一个式子
3.查找
顺序查找 linear Search 时间复杂度O(n)
思路:
- 输入:列表、待查找元素
- 输出:元素下标 (未找到元素时一般返回none或-1
for ind, v in enumerate(li):
if v == val:
return ind
else:
return None
li = [1, 2, 3]
print(linear_search(li, 3))
二分查找 binary_search 时间复杂度log(n)
left = 0
right = len(li) - 1
while left <= right: # 候选区有值
mid = (left + right) // 2
if li[mid] == val:
return mid
elif li[mid] > val:
right = mid - 1
else:
left = mid + 1
else:
return None
li = [1, 2, 31, 4, 5, 3]
res = binary_search(li, 3)
print(res)
4.排序
冒泡排序 时间复杂度 O(n²)
思路:
- 列表每两个相邻的数,如果前面比后面大,则交互这两个数
- 一趟排序完成后,则无序区减少一个数,有序区增加一个数
- 一共运行列表长度-1次
for i in range(len(li)-1): # n-1趟(最后一个没有比的了),第i趟,从0开始
exchange = False
for j in range(len(li)-i-1): # 箭头从0开始,到n-i-1,逐个向上
if li[j]>li[j+1]: # 升序> 降序<
li[j],li[j+1] = li[j+1],li[j]
exchange = True
print(li)
if not exchange:
return
# 生成随机数
# import random
# li= [random.randint(0,10) for i in range(10)]
# print(li)
li = [1,2,3,4,5,6]
bubble_sort(li)
选择排序 select sort 时间复杂度:o(n²)
思路:
- 一趟排序记录最小的数,放到第一个位置
- 再一趟排序记录列表无序区最小的数,放到第二个位置
- 算法关键点:有序区无序区 无序区最小的位置
for i in range(0,len(li)-1):
min_loc = i # 先假定无序区第一个最小
for j in range(i+1,len(li)): # 无序区找最小,比如从第二个到最后,
if li[j] < li[min_loc]:
min_loc = j # 假定第5位最小
li[i],li[min_loc] = li[min_loc],li[i] # 第2位和第5位交换顺序
print(li) # 运行结束打印列表
li = [3,5,1,2,7,8]
res = select_sort(li)
print(li)
插入排序 insert sort 时间复杂度 O(n²)
思路:
- 初始时手里(有序区)只有一张牌
- 每次(从无序区)摸一张牌,插入到手里已有牌的正确位置
def insert_sort(li):
# 比如手里有一张牌了,摸到第二张牌,i=1,j
for i in range(1,len(li)): # i表示摸到的牌下标,不算第一张牌
tmp = li[i] #摸到的牌
j = i-1 # j表示手里的牌
while j >=0 and li[j] > tmp :
li[j+1] = li[j] # 把j往右移
j -=1 # 往左移
li[j+1] = tmp #
print(li)
li = [1,3,1,2,4,5,6,7]
print(li)
insert_sort(li)
快速排序 时间复杂度 :O(nlogn)
思路:
- 取一个元素P(可以是第一个元素),使元素P归位;
- 列表被P分成两部分,左边都比P小,右边都比P大;
- 递归完成排序;
快速排序思路: 可以理解为取出第一个元素5, 从右边第一个找比5小的则放入左边的第一个位置, 然后从左边找比5大的放入右边第一个,依次类推。
def partition(li, left, right): # li表示列表,left,right表示左右边界
tmp = li[left]
while left < right:
while left < right and li[right] >= tmp: # 从右面开始找比tmp小的数
right -= 1 # 往左继续移动
li[left] = li[right] # 找到了,右边的值放到左边的空位上,此时右边出现一个空位
while left < right and li[left] <= tmp:
left += 1
li[right] = li[left] # 把左边的值写到右边的空位上
li[left] = tmp # 把tmp归位
return left
def quick_sort(li, left, right):
if left < right: # 至少右两个元素
mid = partition(li, left, right)
#分开操作
quick_sort(li, left, mid - 1)
quick_sort(li, mid + 1, right)
li = [5, 7, 4, 6, 3, 1, 2, 9, 8]
quick_sort(li,0, len(li) - 1)
print(li)
快排的问题
- 涉及递归