算法设计与分析——递归与分治策略

1. 递归算法

1.1 特点

1.2 优缺点

优点:结构清晰、可读性强

缺点:运行时效率较低,耗费较多的时间、空间资源

2. 分治策略

2.1 基本思想

分治策略的基本思想是将一个规模为n的问题分解为k个较小的子问题,这些子问题互相独立,并且和原问题相同,递归的求解这些子问题,然后将各个子问题的解合并到原问题的解。

2.2 适用的条件

(1)该问题的规模缩小到一定的程度就可以容易地解决;

(2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;

(3)利用该问题分解出的子问题的解可以合并为该问题的解;

(4)原问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。

2.3 求解过程(步骤)

(1)分解:将原问题分解为若干个规模较小、相互独立、与原问题形式相同的子问题。

(2)解决:若子问题规模较小而容易解决则直接解决,否则递归地解各个子问题。

(3)合并:将各个子问题的解合并为原问题的解。

3. 典型算法案例

3.1 二分搜索

3.1.1 非递归实现

  1. 代码实现
/**
 * 二分查找(非递归实现)
 * @param a      数据
 * @param x      待查找的元素
 * @param n      数组长度
 * @return      若查找到,用于带回元素的位置
 */
int BinarySearch(int a[], const int& x, int n){
    int left = 0;
    int right = n-1;
    while (left <= right){
        int middle = (left + right) / 2;
        if (x==a[middle]) return middle;        // 查找成功
        if (x > a[middle])  left = middle+1;    // x大于中间的值时,说明x位于数组的后半段,跟新left的值
        else right = middle-1;                  // x小于中间的值时,说明x位于数组的前半段,跟新right的值
    }
    return -1;      // 查找失败
}

需要先对数组data进行升序排序。

  1. 时间复杂度

2的k次方 > n,k为 int middle = (left + right) / 2; 执行的次数,因此T=O(log2n)。

3.1.1 递归实现

  1. 代码实现
/**
 * 二分查找(递归实现)
 * @param a         数据
 * @param x         待查找值
 * @param left      左指针
 * @param right     右指针
 * @return          返回key的下标
 */
int DGSearch(int a[], const int& x,int left, int right){
    if (right < left)   return -1;                              // 查找失败
    int middle = (left + right) / 2;                            // 设置中间指针
    if (x < a[middle])  DGSearch(a,x,left,middle-1);        // x位于数组的前半段
    else if (x > a[middle]) DGSearch(a,x,middle+1,right);    // x位于数组后半段
    else return middle;                                         // 查找成功
}
  1. 时间复杂度

与非递归算法实现的时间复杂度相同。

image-20210609155552829

3.2 棋盘覆盖问题

3.2.1 L型骨牌放置顺序

棋盘覆盖中,L型骨牌放置的顺序是先将原问题分割为相同类型的子问题,即让其他四分之三的也都各有一个被覆盖的格子。然后对这些子问题按照从左上、到右上、左下、右下的顺序,填充L型骨牌;当每到一个较小的正方形当中,就在中心放置L型骨牌,将原问题化简为四个相同类型的子问题,然后在进行子问题的填充,直到填充完毕。

3.2.2 时间复杂度

image-20210611191246286

T(k) = O(4^k)。

3.3 快速排序

3.3.1 案例解释

  • 方式一(i、j分次序向中间移动)

对(49,38,65,97,76,13,27,49)进行排序

在这里插入图片描述

  • 方式二

i、j 同时向中间移动,j 找到小于基准值的就停下,i 找打大于基准值的就停下,然后将 i、j 相互交换,当 i = j 时,将该位置的值与基准值互换,然后递归的进行下去,知道左右子集均为 1 个元素。

该方式更高效。

3.3.2 复杂度分析

快速排序的时间主要耗费在划分操作上,对长度为n的区间进行划分,共需n-1次关键字的比较,时间复杂度为O(n)。

对n个记录进行快速排序的过程构成一棵递归树,在这样的递归树中,每一层至多对n个记录进行划分,所花时间为O(n)。

当初始排序数据正序或反序时,此时的递归树高度为n,快速排序呈现最坏情况,即最坏情况下的时间复杂度为O(n2);当初始排序数据随机分布,使每次分成的两个子区间中的记录个数大致相等,此时的递归树高度为log2n,快速排序呈现最好情况,即最好情况下的时间复杂度为O(nlog2n)。

  • 最坏时间复杂度:O(n2)
  • 最好时间复杂度:O(nlog2n)
  • 平均时间复杂度:O(nlog2n)
  • 1
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

krain.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值