算法设计与分析之分治思想

算法基础

问题求解的关键

建模:
    对输入参数和解给出形式化或半形式化的描述

设计算法:
    采用什么算法设计技术
    正确性--是否对所有的实例都得到正确的解

分析算法--效率

算法+数据结构=程序

好的算法

提高求解问题的效率
节省存储空间

算法的研究目标

问题->建模并寻找算法        算法设计技术
算法->算法的评价            算法分析方法
算法类-> 问题复杂度估计     问题复杂度分析
问题类-> 能够求解的边界     计算复杂性理论

算法

有限条指令的序列
这个指令序列确定了解决某个问题的一系列运算或操作

算法A解问题P

  • 把问题P的任何势力作为算法A的输入

  • 每步计算是确定性的

  • A能够在有限步停机输出该实例的正确的解


算法时间复杂度:针对指定基本运算,计数算法所做运算次数

基本运算:比较,加法,乘法,置指针,交换。。。。

输入规模:输入串编码的长度。 比如:数组元素多少,调度问题的任务个数

算法基本运算次数可表为输入规模的函数 
给定问题和基本运算就决定了一个算法类

算法的两种时间复杂度

  • 最坏情况下的时间复杂度W(n)

  • 平均情况下的时间复杂度A(n)


分治策略的基本思想

分治策略
    将原始问题划分或者归结为规模较小的子问题
    递归或迭代求解每个子问题
    将子问题的解综合得到原问题的解

注意:
    子问题与原始问题性质完全一样
    子问题之间可彼此独立地求解
    递归停止时子问题可直接求解

分治算法的特点:

将元问题归约为规模小的子问题,子问题与原问题具有相同的性质;
子问题规模足够小时可直接求解;
算法可以递归也可以迭代实现;
算法的分析方法:递推方程

分治算法设计要点

原问题可以划分或者归约为规模较小的子问题
    子问题与原问题具有相同的性质;
    子问题的求解彼此独立
    划分时子问题的规模尽可能均衡

子问题规模足够小时可直接求解
子问题的解综合得到原问题的解
算法实现:递归或迭代

分治算法之快速排序

基本思想
    用首元素x作划分标准,将输入数组A划分成不超过x的元素构成的数组AL,大于x的元素构成的数组AR,其中AL,AR从左到右存放在数组A的位置。

    递归地对子问题AL和AR进行排序,直到子问题规模为1时停止
伪码
    算法 Quicksort(A,p,r)
    输入: 数组A[P..r]
    输出: 排好序的数组A

        1. if p<r
        2. then q <- Partition(A,p,r)
        3.      A[p] <-> A[q]
        4.      Quicksort(A,p,q-1)
        5.      Quicksort(A,q+1,r)

    划分过程:
        Partition(A,p,r)
        1. x ← A[p]
        2. i ← p
        3. j ← r+1
        4. while true do
        5.     repeat j ← j-1
        6.      until A[j] <=x //不超过首元素
        7.      repeat i ← i+1
        8.      until A[i] > x  //比首元素大的
        9.      if i<j
        10.     then A[i] ←→ A[j]
        11.     else return j

时间复杂度

  • 最坏情况: 
    W(n)=W(n-1)+n-1 
    W(1)=0 
    W(n)=n(n-1)/2

  • 最好划分 
    T(n)=2T(n/2)+n-1 
    T(1)=0 
    T(n)=θ(nlogn)

小结

快速排序算法

  • 分治策略

  • 子问题划分时由首元素决定

  • 最坏情况下时间O(n的2次方)

  • 平均情况下时间为O(nlogn)

幂乘算法及应用

幂乘问题

输入: a为给定实数,n为自然数 
输出:a的n次方 
传统算法:顺序相乘 
a的n次方=(….(((a a)a)a)..)a 
乘法次数:θ(n)

分治算法——划分 

分治算法分析 
以乘法作为基本运算

  • 子问题规模,不超过n/2

  • 两个规模近似n/2的子问题完全一样,只要计算1次 
    W(n)=W(n/2)+θ(1) 
    W(n)=θ(log n)

幂乘算法的应用

Fibonacci数列:1,1,2,3,5,8,13,21,…. 
增加F0=0,得到数列:0,1,1,2,3,5,8,13,21…. 
问题:已知F0=0,F1=1,给定n,计算Fn

通常算法:从F0,F1,….开始,根据递推公式:F(n)=F(n-1)+F(n-2) 
陆续相加可得Fn,时间复杂度为θ(n)

Fibonacci数的性质 

算法: 
令矩阵 ,用乘幂算法计算 
时间复杂度:

  • 矩阵乘法次数 T(n)=θ(log n)

  • 每次矩阵乘法需要8次元素相乘

  • 总计元素相乘次数为θ(log n)

改进分治算法的途径1:减少子问题数

减少子问题个数的依据

分治算法的时间复杂度方程

W(n)=a*W(n/b)+d(n)

a:子问题数,n/b:子问题规模, 
d(n):划分与综合工作量

当a较大,b较小,d(n)不大时,方程的解: 

减少a是降低函数W(n)的阶的途径 
利用子问题的依赖关系,使某些子问题的解通过组合其他字问题的解而得到

例子:矩阵相乘的问题

矩阵乘法的研究及应用

矩阵乘法问题的难度:

  • Coppersmith-Winograd 算法: 目前为止最好的上界

  • 目前最好的下界: 
    应用

  • 科学计算、图像处理、数据挖掘等

  • 回归、聚类、主成分分析、决策树等挖掘算法常涉及大规模矩阵运算

改进途径小结
  • 适用于:子问题个数多,划分和综合工作量不太大,时间复杂度函数 

  • 利用自问题依赖关系,用某些子问题解的代数表达式表示另一些子问题的解,减少独立计算子问题个数。

  • 综合解的工作量不影响W(n)的阶。

改进分治算法的途径2:增加预处理

例子:平面点对问题

输入:平面点集P中有n个点,n>1 
输出:P中的两个点,其距离最小

蛮力算法: 
C(n,2)个点对,计算最小距离,O(n的2次方)

分治策略:P划分为大小相等的PL和PR

算法伪码: 

算法分析:

增加预处理: 
原算法: 
在每次划分时对子问题数组重新排序

改进算法:

  1. 在递归前对X,Y排序,作为预处理

  2. 划分时对排序的数组X,Y进行拆分,得到针对子问题PL的数组XL,YL及针对子问题PR的数组XR,YR

    原问题规模为n,拆分的时间为O(n)

改进算法时间复杂度 

改进分治算法的途径:小结

依据

W(n)=a*W(n/b)+f(n)

提高算法效率的方法:

  • 减少子问题个数a: 

  • 增加预处理,减少f(n)

分治算法典型应用:

选第二大

输入:n个数的数组L 
输出:第二大的数 second

通常算法:顺序比较

  1. 顺序比较找到最大max

  2. 从剩下n-1个数中找最大,就是第二大second

    时间复杂度:W(n)=n-1+n-2=2n-3

提高效率的途径

  • 成为第二大数的条件:仅在与最大数的比较中被淘汰

  • 要确定第二大数,必须找到最大数

  • 在确定最大数的过程中记录下被最大数直接淘汰的元素

  • 在上述范围(被最大数直接淘汰的数)内的最大数就是第二大数

  • 设计思想:用空间换时间

锦标赛算法

  1. 两两分组比较,大者进入下一轮,知道剩下1个元素max为止。

  2. 在每次比较中淘汰较小元素,将被淘汰元素记录在淘汰它的元素的链表上

  3. 检查max的链表,从中知道最大元素,即second

伪码 
算法 FindSecond 
输入:n个数的数组L,输出:second

  1. k <- n //参与淘汰的元素数

  2. 将k个元素两两1组,分成[k/2]组

  3. 每组的2个数比较,找到较大数

  4. 将被淘汰数记入较大数的链表 
    =======一轮淘汰结束==============

  5. if k 为奇数 then k <- [k/2]+1

  6. else k <- [k/2]

  7. if k>1 then geto 2 //继续分组淘汰

  8. max <- 最大数

  9. second <- max 的链表中的最大

    实例 

时间复杂度分析

第一阶段元素数:n 
比较次数:n-1 
淘汰了n-1个元素

第二阶段:元素数[log n] 
比较次数:[log n]-1 
淘汰元素数为[log n]-1

时间复杂度是 
W(n)=n-1+[log n]-1=n+[log n]-2

小结

小结:分治算法设计
  • 将元问题归约为子问题:

    • 直接划分注意尽量均衡

    • 通过计算归约为特殊的子问题

    • 子问题与原问题具有相同的性质

    • 子问题之间独立计算

  • 算法实现:

    • 递归或迭代实现

    • 注意递归执行的边界

小结:分治算法的分析及改进
  • 时间复杂度分析: 

    • 给出关于时间复杂度函数的递推方程和初始值

    • 求解方程

  • 提高效率的途径:

  • 减少子问题个数

  • 预处理

小结: 重要的分治算法
  • 检索算法:二分检索

  • 排序算法:快速排序、二分归并排序

  • 选择算法: 选最大与选最小、选第二大

  • 快速傅里叶变换FFT算法

  • 平面点集的凸包


更多关于hadoop,spark和机器学习文章请关注本文公众号:


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值