万物不为我所有,但为我所用|

注入灵魂

园龄:3年7个月粉丝:3关注:2

2022-03-18 16:14阅读: 65评论: 0推荐: 0

数据结构与算法【进阶】

贪心算法

在对问题求解时,总市做出当前看来时最好的选择。

  1. 不从整体最优上考虑
  2. 局部最优解

找零问题

假设商店老板需要找零n元钱,钱币的面额:100元、50元、20元、5元、1元,如何找零使得所有钱币数量最少?

t = [100,50,20,5,1]
def change(t,n):
m = [0 for _ in range(len(t))]
for i,money in enumerate(t):
m[i] = n // money
n = n % money
return m,n

背包问题

一个小偷在某个商店发现右n个商品,第i个商品价值vi元,重wi千克。他希望拿走的价值尽量高,但他的背包子最多只能容纳W千克的东西。他应该拿走哪些商品?

0-1背包:对于一个商品,小偷要么把它完整拿走,要么留下。不能只拿走一部分,或把一个商品拿走多次。(商品为金条)

分数背包:对于一个商品,小偷可以拿走其中任意一部分。(商品为金砂)

goods = [(60,10),(100,20),(120,30)] #(价格,重量)
goods.sort(key=lambda x:x[0]/x[1],reverse=True)
def fractional_backpack(goods,w):
m = [0 for _ in range(len(goods))]
for i,(price,weight) in enumerate(goods):
if w >= weight:
m[i]=1
w -= weight
else:
m[i] = w / weight
w = 0
break
return m

拼接最大数字问题

有n个非负整数,将其按照字符串拼接的方式拼接为一个整数。如何拼接可以使得得到的整数最大?

from functools import cmp_to_key
li = [32,94,238,1286,6,71]
def xy_cmp(x,y):
if x+y < y+x:
return 1
elif x+y > y+x:
return -1
else:
return 0
def number_join(li):
li = list(map(str,li))
li.sort(key=cmp_to_key(xy_cmp))
return "".join(li)

活动选择问题

假设有n个活动,这些活动要占用同一片场地,而场地在某时刻只能共一个活动使用

每个活动都有一个开始时间si和结束时间fi,表示活动在[si,fi)区间占用场地

问:安排哪些活动能够使该场地举办的活动的个数最多?

i 1 2 3 4 5 6 7 8 9 10 11
si 1 3 0 5 3 5 6 8 8 2 12
fi 4 5 6 7 9 9 10 11 12 14 16

贪心结论:最先结束的活动一定是最优解的一部分

activities = [(1,4),(3,5),(8,6),(5,7),(3,9),(6,10),(8,11),(8,12),(2,14),(12,16)]
# 保证活动是按结束时间排号序的
activities.sort(key=lambda x:x[1])
def activity_slection(a):
res = [a[0]]
for i in range(1,len(a)):
if a[i][0]>=res[-1][1]: # 当前活动的开始时间小于等于最后一个入选活动的结束时间
# 不冲突
res.append(a[i])
return res

动态规划

  1. 最优子结构(递推式)
  2. 重复子问题,将重复的子问题存起来

斐波那契数列

  1. Fn=Fn-1+Fn-2

  2. 递归求解第n项

    def fib(n):
    if n == 1 or n == 2:
    return 1
    else:
    return fib(n-1)+fib(n-2)
    '''
    为什么递归效率低?
    因为有重复计算
    f(5)=f(4)-f(3)
    f(4)=f(3)-f(2)
    '''
    # 此处循环方法使用的动态规划思想
    def fib_no_rec(n):
    f = [0,1,1]
    if n > 2:
    for i in range(n-2):
    num = f[-1]+f[-2]
    f.append(num)
    return f[n]

钢条切割问题

某公司出售钢条,出售价格与钢条长度之间的关系如下表:

长度i 1 2 3 4 5 6 7 8 9 10
价格pi 1 5 8 9 10 17 17 20 24 30

问题:现有一段长度为n的钢条和上面的价格表,求切割钢条方案,使得总收益最大

思考:长度为n的钢条的不同切割方案有几种

image

image

image

p = [0,1,5,8,9,10,17,17,20,24,30]
# 递归方法
def cut_rod_recurision_1(p,n):
if n==0:
return 0
else:
res = p[n]
for i in range(1,n):
res = max(res,cut_rod_recurision_1(p,i)+cut_rod_recurision_1(p,n-i))
return res
# 自顶向下实现
def cut_rod_recurision_2(p,n):
if n == 0:
return 0
else:
res = 0
for i in range(1,n+1):
res = max(res,p[i]+cut_rod_recurision_2(p,n-i))
return res

image

# 自底向上实现
def cur_rod_dp(p,n):
r = [0]
for i in range(1,n+1):
q = 0
for j in range(1,i+1):
q = max(q,p[j]+r[i-j])
r.append(q)
return r[n]
# 最优解+最优切割方案
def cur_rod_extend(p,n):
r = [0]
s = [0]
for i in range(1,n+1):
res_r = 0 # 价格的最大值
res_s = 0 # 价格最大值对应方案的左边不切割部分的长度
for j in range(1,i+1):
if p[j] + r[i-j] > res_r:
res_r = p[j]+r[i-j]
res_s = j
r.append(res_r)
s.append(res_s)
return r[n],s
def cut_rod_solution(p,n):
r,s = cur_rod_extend(p,n)
ans = []
while n > 0:
ans.append(s[n])
n -= s[n]
return ans

时间复杂度O(n²)

image

最长公共子序列

image

image

image

image

# 动态规划法
def lcs_length(x,y):
m = len(x)
n = len(y)
c = [[0 for _ in range(n+1)] for _ in range(m+1)]
for i in range(1,m+1):
for j in range(1,n+1):
if x[i-1] == y[j-1]: # i j 位置上的字符匹配的时候,来自于左上方+1
c[i][j] = c[i-1][j-1]+1
else:
c[i][j] = max(c[i-1][j],c[i][j-1])
return c[m][n]
# 回溯法
def lcs(x,y):
m = len(x)
n = len(y)
c = [[0 for _ in range(n+1)] for _ in range(m+1)]
b = [[0 for _ in range(n+1)] for _ in range(m+1)]
for i in range(1,m+1):
for j in range(1,n+1):
if x[i-1] == y[j-1]: # i j 位置上的字符匹配的时候,来自于左上方+1
c[i][j] = c[i-1][j-1]+1
b[i][j] = 1
elif c[i-1][j] > c[i][j-1]: # 来自上方
c[i][j] = c[i-1][j]
b[i][j] = 2
else: # 来自左方
c[i][j] = c[i][j-1]
b[i][j] = 3
return c[m][n],b
def lcs_trackback(x,y):
c,b = lcs(x,y)
i = len(x)
j = len(y)
res = []
while i>0 and j>0:
if b[i][j] == 1: # 来自左上方
res.append(x[i-1])
i -= 1
j -= 1
elif b[i][j] == 2: # 来自上方
i -= 1
else:
j -= 1
return "".join(reversed(res))

欧几里得算法

最大公约数

gcd(a,b) = gcd(b,a mod b)

def gcd(a,b):
if b == 0:
return a
else:
return gcd(b,a % b)
def gcd2(a,b):
while b>0:
r = a % b
a = b
b = r
return a

实现分数计算

class Fraction:
def __init__(self,a,b):
self.a=a
self.b=b
x = self.gcd(a,b)
self.a /= x
self.b /= x
def gcd(a,b):
while b > 0:
r = a % b
a = b
b = r
return a
def __str__(self):
retunr "%d%d" %(%self.a,self.b)
def zxgs(a,b): # 最小公倍数
x = self.gcd(a,b)
return a*b/x
def __add__(self,other):
a = self.a
b = self.b
c = other.a
d = other.b
fenmu = self.zxgs(b,d)
fenzi = a * fenmu / b + c * fenmu / d
return Fraction(fenzi,fenmu)

RSA算法

现代密码系统:加密算法是公开的,密钥是秘密的

  1. 对称加密
  2. 非对称加密

image

过程

image

image

本文作者:注入灵魂

本文链接:https://www.cnblogs.com/totopian/p/16022286.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   注入灵魂  阅读(65)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 尚好的青春 孙燕姿
尚好的青春 - 孙燕姿
00:00 / 00:00
An audio error has occurred.