递归算法(python)---分治策略、优化问题、贪心策略


分治策略

分而治之:

  • 将问题分为若干更小规模的部分;
  • 通过解决每一个小规模部分问题,将结果汇总得到原问题的解。

递归三定律:

  • 基本结束条件,解决最小规模问题
  • 缩小规模,向基本结束条件演进
  • 调用自身来解决已缩小规模的相同问题

总结: 问题解决依赖于若干缩小了规模的问题汇总得到原问题的解。

应用 排序、查找、遍历、求值等。

优化问题: 算法都是为了找到某些问题的最优解。

LeetCode322. 零钱兑换

在这里插入图片描述
这是一个经典的案例,找零兑换问题。

贪心策略
解决这类问题最直观的就是贪心算法。用尽量多的数量有余额的,再到下一最大面值的货币,直到最后。

因为我们每次都试图解决问题的尽量大的一部分对应到兑换零钱的问题,就是每次以最多数量的最大面值货币来迅速减少找零面值。

贪心策略解决找零兑换问题,在美元或者其他货币的硬币体系下表现尚好。例如:在Elbonia体系中,存在21面值货币;
以63为例;63 = 25*2 + 10*1 + 1*3(美元硬币);
但实际上还有 63 =21*3。

贪心策略失效了。贪心策略是否有效依赖于具体的硬币体系。
美元面值:1美元、5美元、10美元、20美元、50美元和100美元纸币,另有1美分、5美分、10美分、25美分、50美分、1美元硬币。

找零兑换问题:递归解法及其改进

递归解法

货币体系:[1, 5, 10, 25, 50]
基本结束条件:

  • 需要兑换找零,其面值正好等于某种硬币;
  • 减小问题规模;
coinChange = min(
    1 + coinChange(original - 1),
    1 + coinChange(original - 5),
    1 + coinChange(original - 10),
    1 + coinChange(original - 20)
)

递归解法代码:

def coinChange(coinlist, change):
    minCoins = change
    if change in coinlist:
        return 1
    else:
        for i in [c for c in coinlist if c <= change]:
            numCoins = 1 + coinChange(coinlist, change-i)
            if numCoins < minCoins:
                minCoins = numCoins
        return minCoins

print(coinChange([1,5,10,25],63))

输出结果:6种
递归虽然可以解决问题,但是极其低效。
可以用time模块来看一下时间。这是因为重复计算太多。

递归改进解法

改进关键:消除重复计算。
我们可以用一个表将计算过的中间结果保存起来,在计算之前查表看看是否已经计算过。

在递归调用之前,先查找表中是否已有部分找零的最优解;
如果有,直接最优解而不进行递归调用;
如果没有,才进行递归调用。

def coinChange(coinlist, change, knowResults):
    minCoins = change
    if change in coinlist:
        knowResults[change] = 1
        return 1
    elif knowResults[change] > 0:
        return knowResults[change]
    else:
        for i in [c for c in coinlist if c <= change]:
            numCoins = 1 + coinChange(coinlist, change-i, knowResults)
            if numCoins < minCoins:
                minCoins = numCoins
                knowResults[change] = minCoins
        return minCoins

print(coinChange([1,5,10,25],63,[0]*64))

改进之后,极大减少了递归调用次数;63的兑换递归调用是改进前的三十万分之一。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

他是只猫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值