算法3——算法进阶

算法进阶

贪心算法

对问题求解时,总是做出在当前看来是最好的选择.不从整体最优上加以考虑,所做出的是在某种意义上的局部最优解. 不保证会得到最优解,但是在某些问题上贪心算法的解就是最优解. 要会判定一个问题能否用贪心算法来计算.

特殊问题:

  • 找零问题
  • 背包问题(0-1背包/分数背包)
  • 拼接最大数字问题
  • 活动选择问题

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

from functools import cmp_to_key
li = [32,94,128,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)

print(number_join(li))

活动选择问题 假设有n个活动,这些活动要占用用一片场地,而场地在某时刻只能提供一个活动使用. 安排哪些活动能够使该场地举办的活动个数最多?

activities = [(1,4),(3,5),(0,6),(5,7),(3,9),(5,9),(6,10),(8,11),(8,12),(2,14),(12,16)]

activities.sort(key=lambda x:x[1])

def activity_selection(a):
    res = [a[0]]
    for i in range(1,len(a)):
        if a[i][0] >= res[-1][1]:
            res.append(a[i])
    return res


动态规划

最优子结构

可以将求解规模为n的原问题,划分为规模更小的子问题 组合两个子问题的最优解,并在所有肯恩的方案中选取组合收益最大的,构成原问题的最优解 最优子结构:问题的最优解由相关子问题的最优解组合而成,这些子问题可以独立求解

自顶向下 复杂度爆炸

def cut_rod_recurision(p,n):
    if n==0:
        return 0
    else:
        res = p[n]
        for i in range(1,n):
            res = max(res,cut_rod_recurision(p,i) + cut_rod_recurision(p,n-i))
        return res

自下而上 复杂度可控

def cut_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 = cut_rod_extend(p,n)
    ans = []
    while n > 0:
        ans.append(s[n])
        n -= s[n]
    return ans

动态规划问题关键特征

最优子结构

  • 原问题的最优解中涉及多少个子问题
  • 在确定最优解使用哪些子问题时,需要考虑多少种选择 重叠子问题

最长公共子序列问题

欧几里得算法问题

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
print(gcd(12,16))

RSA加密算法

传统密码:加密算法是秘密的

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

  • 对称加密
  • 非对称加密

RSA非对称加密系统: 公钥:用来加密,是公开的 私钥:用来解密,是私有的

RSA加密算法过程

随机选取两个质数p和q 计算n=pq 选取一个与φ(n)互质的小奇数e,φ(n)=(p-1)(q-1) 对模φ(n),计算e的乘法逆元d,即满足(ed) mod φ(n) = 1 公钥(e,n) 私钥(d,n)

加密过程:c = (m^e) mod n 解密过程:m = (c^d) mod n

github address:

https://github.com/chenbokaix250/ForSomeForMySelf

updatedupdated2021-01-122021-01-12