【算法基础】分治思想

1.1分治算法

1.1.1分治算法思想

将原问题分解成与“原问题相同但是规模更小”的子问题,并可以反复执行这个过程,使得问题规模减小到可以求解为止。下面我们将举出是三个例子来介绍分治算法

1.1.2.快速排序

问题描述:给定1000个数,从小到大进行排序。

问题分析: 先选择一个“标准”A,按照“比A小”和“比A大”将原来的数列分为两类,这样,只需要将两个子序列分别排好序,然后再合并到一块就ok了。

快速傅里叶变换

1.1.3.大数相乘算法

问题:两个很大的数相乘,如何更快的解决?

两个很大的数相乘,普通算法的时间复杂度为O(n^2)。该算法将原来的时间复杂度降低到O(3^1.585)

步骤:

首先,将n位大数x和y进行分解。

然后,x·y就变成了下面这样

并且满足

这样的话,乘法又能变成加法了!计算复杂度又大大的降低了!

 

分治思想小结

第一:数学归纳是使用分治思想

第二:分治思想不一定使用递归结构;递归结构是循环结构的一种,也是分治思想应用最多的一种程序结构,但是不一定要使用它!关键在于能够写出递归公式以及是否有必要使用递归算法。比如上边提到的快速傅里叶变换算法,就没有用到递归!

第三:分治思想的核心是“如何分”

采用分治法的时我们会将其划分成比较小的子问题,从子问题中找出局部最优,然后将子问题的局部最优进行合并,这时候就会出现出现重叠子问题和重叠子结构,就需要我们后续的动态规划问题处理....不急,下面将会介绍

2.1.递归算法

2.1.1运用递归需要注意

  • 递归的退出条件
  • 递归时应该传递的参数
  • 递归一定是从后往前的

其实递归也是动态规划的一种思想:下面我们举个例子看看

代码实现

def fblq(n):
    if n<=0:
        return 0
    elif n==1:
        return 1
    else:
        return fblq(n-2)+fblq(n-1)
print(fblq(10))

3.1动态规划

有一座高度是10级台阶的楼梯,从下往上走,每跨一步只能向上1级或者2级台阶。要求用程序来求出一共有多少种走法。(比如,每次走1级台阶,一共走10步,这是其中一种走法。我们可以简写成 1,1,1,1,1,1,1,1,1,1。)

这个问题就用到了动态规划,动态规划是一种分阶段求解决策略的思想参考文档

解决方案:

  • F(1) = 1;
  • F(2) = 2;
  • F(n) = F(n-1)+F(n-2)(n>=3)

动态规划:重叠子结构,边界,状态转移公式

代码实现:

def way(n):
    if n<=0:
        return 0
    if n==1:
        return 1
    if n==2:
        return 2
    return way(n-1)+way(n-2)
print(way(10))

时间复杂度计算:

相同的颜色代表了方法被传入相同的参数。

时间复杂度为O(n**2)

相同元素的值被计算了两次,我们可以使用哈希表将计算的结果暂时存起来,这种方法叫备忘录算法

优化:代码实现

def way(n,ds):
    if n<=0:
        return 0
    if n==1:
        return 1
    if n==2:
        return 2
    if n in ds:
        return ds[n]
    else:
        value=way(n-1,ds)+way(n-2,ds)
        ds[n]=value
        return value
ds=dict()
for i in range(11):
    print(way(i, ds))

时间复杂度为O(n),尽管提高了时间复杂度,但是空间复杂度似乎是降低了,我们能不能也也将空间复杂度提高?当然,我们是自顶向下,为什么不能自底向上尼?F(3)基于F(1)和F(2),而F(4)基于F(2)和F(3),我们可以先计算F(1)和F(2)再计算F(10),这样是不是就降低了存储空间吧

给出一道比较复杂的问题:

有一个国家发现了5座金矿,每座金矿的黄金储量不同,需要参与挖掘的工人数也不同。参与挖矿工人的总数是10人。每座金矿要么全挖,要么不挖,不能派出一半人挖取一半金矿。要求用程序求解出,要想得到尽可能多的黄金,应该选择挖取哪几座金矿?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值