算法与复杂度学习--week3:求相邻最近的点;阶乘(递归法、循环法);斐波那契数列(递归法,循环法);汉诺塔问题(递归法);零钱问题(递归法);字符串匹配

○ 求相邻最近的点

在这里插入图片描述

  • 注意,在这里首先声明了 m i n = f l o a t ( " i n f " ) min = float("inf") min=float("inf") 这句话的意思是, m i n min min 初始化的值为正无穷。

○ 阶乘

递归法

在这里插入图片描述

循环法

  • 使用 for 循环
    在这里插入图片描述
  • 使用 while 循环
    在这里插入图片描述

○ 斐波那契数列

递归法

在这里插入图片描述

※ 循环法(这个思路牛逼)

在这里插入图片描述

○ 汉诺塔(Hanoi)

在这里插入图片描述

  • H a n o i ( ) Hanoi() Hanoi() 函数里面的参数意义分别是:
    • n n n:一共有 n n n 个盘子
    • a a a:起始的柱子
    • b b b:中间的柱子
    • c c c:最终的柱子
  • 算法解析:
    • 如果有 1 1 1 个盘子,那么直接从 a → c a→c ac
    • 如果有 2 2 2 个盘子,那么需要先把最上面的盘子 a → b a→b ab, 再把最后一个盘子从 a → c a→c ac,再把第一个盘子从 b → c b→c bc
    • 如果有 n n n 个盘子,我们应该把整个搬移过程模式化,那就是我们总是试图通过借助柱子 b b b 将上面 n − 1 n-1 n1 个盘子从 a → b a→b ab,然后再把最后一个盘子从 a → c a→c ac,再把上面的 n − 1 n-1 n1 个盘子从 b → c b→c bc,而上面 n − 1 n-1 n1 个盘子的移动过程,我们把他们都可以看做是一个的小汉诺塔问题。这就是解决问题的关键。
    • 而问题的出口就是最后一个盘子,当存在唯一一个盘子的时候,它本身就是最后一个盘子,因此直接 a → c a→c ac 即可,而如果不是一个盘子,我们就需要先挪动上面 n − 1 n-1 n1 个盘子,再操作最后一个盘子。
    • H a n o i ( n , a , b , c ) Hanoi(n,a,b,c) Hanoi(n,a,b,c) 的意思就是:将 n n n 个盘子,从 a a a 借助 b b b 移到 c c c;因此 H a n o i ( n − 1 , a , c , b ) Hanoi(n-1,a,c,b) Hanoi(n1,a,c,b) 的意思就是:将 n − 1 n-1 n1 个盘子,从 a a a 借助 c c c 移动到 b b b

○ ※ 零钱问题(递归法)

  • 题目描述:给定一个具体数额 amount = 10元,从一个面值 denomination 集合中(6,2, 1)中每次使用一个数字,使得最终能够凑满 10 元钱,问这样的解有多少个。
    在这里插入图片描述
    在这里插入图片描述

  • 看这个图可能会有助于理解,题目中的关键就在于递归的公式,最后的 return ways(amount - d, denominations) + ways(amount, denominations.difference([d]))

  • 前半个公式:return ways(amount - d, denominations) 表示的是图中红线的部分,第一个 stage 随机选择的面值是 1,那么自然而然下一个 stage 的起始 amount = 10 - 1 = 9;第二个 stage 我们选择的面值是 2,那么下一个 stage 的起始 amount = 9-2 = 7,这个没有任何问题。那为什么这个公式还有后面一半: ways(amount, denominations.difference([d])) 呢???

  • 原因就是,如果我们只考虑公式的前半部分,我们最终返回的结果只能包含红线这一条线路;而不能考虑到其他的选择。如果我们看到后面的公式我们就会发现, ways(amount, denominations.difference([d])) 中,amount 并没有减 d ,而是维持了 amount,而 demomination 的部分却排除了本 stage 中被选择的面值

  • 简单地来说,如果前半部分的公式是不断地向深度搜索一条满足条件的路,那么公式的后半部分表示的,就是在每一步骤的时候,所有并行的可能。当第一个 **stage:10 **已经选择了面值 1,此时的第二个部分的公式就会返回 10 选择面值 8 和 面值 4 的可能并向深度进行探索。

  • 如果还没有明白,可以根据下面的图看,会辅助你理解。
    在这里插入图片描述

  • 零钱问题使用递归的方法并不是最高效的,因为他的复杂度是指数型增长的,比较常用的方法是动态规划,后面会涉及

○ 字符串匹配

在这里插入图片描述

  • 首先在 text 文字中进行的循环次数,不需要将 text 全部进行循环,因为如果 text 包含 pattern,那么最多需要查询的情况就是 text 长度 - pattern 的长度加一次。
  • 当 text 中出现了 pattern 的第一个字母就可以开启检测的过程了
  • 整个检测过程使用一个 while 或 for 循环来完成,循环的次数是 pattern 的长度次;当然也可以是 pattern 长度- 1 次,这样的话就必须 count 从 1 开始计数(把 pattern[0] = text[i] 这一次也算在其中),即如下图所示
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暖仔会飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值