算法图解阅读笔记

二分查找

  • 二分查找比简单查找快
  • 算法运行时间以增速度量大O表示法,不以秒为时间单位
  • O(log n)比O(n)快
# 二分查找
def midsearch(data,target):
	low=0
	high=len(data)-1
	while low<=high: #这里是<=因为要运行到范围只有一个元素的时候
		mid=int((low+high)/2)
		if target==data[mid]:
			return True
		if target<data[mid]:
			high=mid-1
		else:
			low=mid+1
	return False

data=[1,2,4,5,7,9]
target1=11
target2=9

print(midsearch(data,target1))
print(midsearch(data,target2))

数组和链表

  • 数组和链表的区别:数组地址是连续的,链表不连续
数组链表
读取O(1)O(n)
插入删除O(n)O(1)
  • 同一数组中,数据类型需要保持一致

递归

  1. 一般来说,循环可以获得更好的性能,而递归(调用栈消耗内存和影响性能)更好理解
  2. 基线递归,加入基线条件,避免无限调用

分治法

分治法:

  1. 找出简单的基线条件
  2. 确定如何缩小问题的规模,使其符合基线条件

欧几里得算法:求最大公约数

def GCD(a,b):
	print("GCD:",a,b)
	if a%b==0:
		return b
	else:
		return GCD(b,a%b)
print(GCD(72,27))

快速排序

# 非原地
def quicksort(array):
	if len(array)<2:
		return array
	else:
		pivot=array[0]
		less=[i for i in array[1:] if i<=pivot]
		greater=[i for i in array[1:] if i>pivot]
		return quicksort(less)+[pivot]+quicksort(greater)
# 原地		
def quicksort(array, l, r):
    if l < r:
        q = partition(array, l, r)
        quick_sort(array, l, q - 1)
        quick_sort(array, q + 1, r)
        
def partition(array, l, r):
    privot = array[r]
    i = l 
    for j in range(l, r):
        if array[j] <= privot:
            array[i], array[j] = array[j], array[i]
            i+=1
    array[i], array[r] = array[r], array[i]
    return i

归并排序

def merger_sort(L):
    if len(L)<=1:
        return L
    mid=int(len(L)/2)
    left=merger_sort(L[:mid])
    right=merger_sort(L[mid:])
    return merge(left,right)

def merge(left,right):
    l,r=0,0
    res=[]
    while l<len(left) and r<len(right):
        if left[l]<right[r]:
            res.append(left[l])
            l+=1
        else:
            res.append(right[r])
            r+=1
        
    res+=list(left[l:])
    res+=list(right[r:])
    
    return res

散列表

  • 平均查询修改的时间都是O(1),但是最糟情况下的时间是O(n)
  • 一般经验来说,一旦装填因子大于0.7就要调整散列表的长度
  • Python中简单使用{}来创建一个散列表

广度优先搜索

  • 图由节点和边组成
  • 相连的节点互为邻居
  • 可以通过散列表来建立图
  • 树是一种特殊的图,没有向后的边

广度优先搜索

  • 从根节点出发,先遍历完每个邻居,再去遍历邻居的邻居(不包含已经访问过的节点)
  • 可以通过队列(FIFO)实现
  • 栈是(LIFO)

狄克斯特拉算法

  • 狄克斯特拉算法可以用于求有向无环图最短路径问题(不包含负权边)
  • 当包含负权边时,使用贝尔曼-福德算法

贪心算法

  • 贪心算法,每步都采取最优的做法
  • 贪心算法,不一定能取得最优解,但是能取得近优解
  • NP完全问题,无法在多项式时间内快速解决的问题

动态规划

  • 动态规划可以帮助在给定的约束条件下寻找到最优解
  • 解决一个问题的过程可以分解为解决子问题的情况下,就可以用动态规划解决
  • 典型的动态规划问题如背包问题

01背包

# bag 6
# a(3,10)
# b(1,3)
# c(2,9)
# d(2,5)
# e(1,6)

def solve2(vlist,wlist,totalWeight):
    totalLength=len(vlist)
    resArr = [0]*(totalWeight+1)
    for i in range(1,totalLength):
        for j in range(totalWeight,0,-1):
            if wlist[i] <= j:
                resArr[j] = max(resArr[j],resArr[j-wlist[i]]+vlist[i])
        print(resArr)
    return resArr[-1]


v = [0,10,3,9,5,6]
w = [0,3,1,2,2,1]
weight = 6
result = solve2(v,w,weight)
print(result)

完全背包

只是内循环顺序不同

# bag 6
# a(3,10)
# b(1,3)
# c(2,9)
# d(2,5)
# e(1,6)

def solve2(vlist,wlist,totalWeight):
    totalLength=len(vlist)
    resArr = [0]*(totalWeight+1)
    for i in range(1,totalLength):
        for j in range(1,totalWeight+1):
            if wlist[i] <= j:
                resArr[j] = max(resArr[j],resArr[j-wlist[i]]+vlist[i])
        print(resArr)
    return resArr[-1]
v = [0,10,3,9,5,6]
w = [0,3,1,2,2,1]
weight = 6
result = solve2(v,w,weight)
print(result)

多重背包

而已转化为0 1把背包解决

最长公共子序列 子串

两个个注意的地方:

  • 创建二维数组的大小为m*n
  • 最长公共子序列的大小位于右下角
# 最长公共子序列
def comp_sequence(str1,str2):
    m=len(str1)
    n=len(str2)
   
    w=[[0]*(n) for i in range(m)]
    #辅助记录结果0表示斜向上,-1表示向上,1表示向左
    c=[[0]*(n) for i in range(m)]
    for i in range(0,m):
        for j in range(0,n):
            if str1[i]==str2[j]:
                w[i][j]=w[i-1][j-1]+1
            elif w[i-1][j]>w[i][j-1]:
                w[i][j]=w[i-1][j]
                c[i][j]=-1
            else:
                w[i][j]=w[i][j-1]
                c[i][j]=1
    # 回溯最长子序列
    subs=""
    i=m-1
    j=n-1
    while i>=0 and j>=0:
        if c[i][j]==0:
            subs=str1[i]+subs
            i-=1
            j-=1
        elif c[i][j]==-1:
            i-=1
        else:
            j-=1
            
    print(w[-1][-1],subs)
    
# 最长公共子串
def comp_string(str1,str2):
    m=len(str1)
    n=len(str2)
   
    w=[[0]*(n) for i in range(m)]
    lmax=0
    subs=""
    for i in range(0,m):
        for j in range(0,n):
            if str1[i]==str2[j]:
                w[i][j]=w[i-1][j-1]+1
            else:
                w[i][j]=0
            #记录更新子串
            if w[i][j]>lmax:
                lmax=w[i][j]
                subs=str1[i+1-lmax:i+1]
    
    print(lmax,subs)
    

str1="foitksh"
str2="fitqsh"
        
comp_sequence(str1,str2)
comp_string(str1,str2)

总结来说,如果解决问题可以通过解决子问题(画网格),那么这个问题就很适合用动态规划解决。

K最近邻算法

特征提取>>度量距离>>分类或回归


后面高阶内容单独再写吧,嗯,可以开始刷题了呢~~~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值