【算法分析】分治法详解+范例+习题解答

🦄1.分治法(Divide-and-Conquer)

1.1分治法的设计思想

将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,
分而治之

1.2分治法的适用条件

  • 该问题的规模缩小到一定的程度就可以容易地解决;
  • 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质
  • 利用该问题分解出的子问题的解可以合并为该问题的解;
  • 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。这条特征涉及到分治法的效率,如果各子问题是不独立的,则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然也可用分治法,但一般用动态规划较好。

1.3分治法的基本步骤

divide-and-conquer(P)
{
    if ( | P | <= n0) adhoc(P);   //解决小规模的问题
    divide P into smaller subinstances P1,P2,...,Pk;//分解问题
    for (i=1,i<=k,i++)
      yi=divide-and-conquer(Pi);  //递归的解各子问题
    return merge(y1,...,yk); //将各子问题的解合并为原问题的解
  } 

1.4主定理Master Theorem

在这里插入图片描述

🦄2.范例

2.1合并排序

2.1.1 基本思想

将待排序元素分成大小大致相同的2个子集合,分别对2个子集合进行排序,最终将排好序的子集合合并成为所要求的排好序的集合。
在这里插入图片描述

2.1.2 伪代码实现

public static void mergeSort(Comparable a[], int left, int right)
   {
      if (left<right) 
      {//至少有2个元素
        int i=(left+right)/2;  //取中点
        mergeSort(a, left, i);
        mergeSort(a, i+1, right);
      	merge(a, b, left, i, right);  //合并到数组b
      	copy(a, b, left, right);    //复制回数组a
      }
   }

在这里插入图片描述

2.1.3 复杂度分析【nlogn】

在这里插入图片描述
T(n)=Θ(nlogn) 渐进意义下的最优算法

2.2 二分搜索

给已排好序的n个元素中寻找特定元素x

2.2.1 基本思想

  • 该问题的规模缩小到一定的程度就可以容易地解决
  • 该问题可以分解为若干个规模较小的相同问题;
  • 分解出的子问题的解可以合并为原问题的解;
  • 该问题具有最优子结构性质;

2.2.2 伪代码实现

在这里插入图片描述

2.3.3 复杂度分析【最坏logn】

2.3 Strassen矩阵乘法

A和B的乘积矩阵C中的元素C[i,j]定义为
在这里插入图片描述
传统方法:O(n3)【计算时,三个for循环】

2.3.1基本思想

为了降低时间复杂度,必须减少乘法的次数
在这里插入图片描述

2.3.2 复杂度分析【nlog7 =n 2.81

在这里插入图片描述

2.4 大整数乘法

请设计一个有效的算法,可以进行两个n位大整数的乘法运算

2.4.1基本思想

为了降低时间复杂度,必须减少乘法的次数
XY = ac 2n + (ad+bc) 2n/2 + bd

🦄3.习题

3.1 指定序号元素查找

1,查找数组a[n]中的最大元素,至少需要多少次比较?
2,查找数组a[n]中的最大和最小元素,用最少的元素比较次数。
3,查找数组a[n]中的第k小的元素(k相对于n比较小);
4,查找数组a[n]中的中位数(序号为n/2);

3.2设计算法

设计算法,找出数组a[n]的中位数。
设计算法,找出数组a[n]中序为k的数。
设计算法,输出数组a[n]中所有序为奇数的数。
设计算法,计算序列a[n]中的逆序数

3.3矩阵走法

  1. 有一个5×4的矩阵,从左上角的格子开始每次只能向右或者向下走,最后到达右下角的位置,总共有多少种走法?
    在这里插入图片描述

  2. 有一个矩阵,从左上角的格子开始每次只能向右或者向下走,最后到达右下角的位置,求解总共有多少种走法的函数f(x,y),可以理解x是方格的横坐标、y是纵坐标,x≥0,y≥0。 定义f(0,0)=0,f(x,1)=1, f(1,y)=1, 其它情况f的递归定义是()。
    答: f(x,y) =f(x-1,y)+f(x,y-1)

  3. 某段楼梯有10级台阶,每次只能跨一级或两级,爬上这段楼梯共有______种走法?
    在这里插入图片描述
    4.要拼一个1×7长方形,可用的纸片有以下规格:1×1, 1×2, 1×3,共有______种拼法?
    == 解:f(n) = f(n-1)+f(n-2)+f(n-3) 1,2,4,7,13,24,44==

3.4排序

3.4.1合并排序

如果再合并排序算法的分割步中,将数组a[0:n-1]划分为⌊√n⌋个子数组,每个子数组中有O(√n)个元素。然后递归地对子数组进行排序,最后将所得到的个排好序的子数组合并成所要求的排好序的数组。以上排序算法的平均时间复杂度是多少?
Θ(√n*log√n)

3.4.2快速排序

low和high是索引

void QuickSort ( SqList &L, int low, int high ){
//在序列lowhigh 中递归地进行快速排序
    if ( low < high) {					
       int p= Partition (L, low, high);   //p作为中间值索引进行划分
           
       QuickSort ( L, low, p-1 ); //对左序列递归处理
       QuickSort ( L, p+1, high); //对右序列递归处理
    }
}

int Partition ( SqList &L, int low, int high ) {
   pivotkey = L.r[low].key; //基准对象关键字【找第一个数字】
   while(low<high){

👇这个while先把所有小于基准的放左边
       while(low<high && L.r[high].key >= pivotkey) high--;//如果大于基准值则high--,换下一个比较
       L.r[low]  L.r[high]; //小于基准对象的移到区间的左侧
       
👇这个while再把所有大于基准的放右边
       while(low<high&& L.r[low].key <= pivotkey) low++;
       L.r[high]  L.r[low] ; //大于基准对象的移到区间的右侧
   }    
   return low;
}

Partition函数作用:通过基准将数组分成两部分,小于基准的在基准左边,大于则在右边。Partition时间复杂度Θ(n)

3.4.2.1复杂度

平均时间复杂度Θ(n*logn)
最坏时间复杂度O(n2)
平均空间复杂度O(logn),logn次都需要一个空间存基准

3.5线性时间选择算法

  1. 关于线性时间选择算法select中,每5个元素划为一组,并将所有组的中位数合成一个“短数组”,下列说法中正确的是
    == “短数组”的长度大约为n/5;“短数组”的中位数将作为select的基准元==

3.6快速排序中第k小的元素的算法

可基于快速排序中的划分算法Partition (int a[], int low, int high)完成查找数组a[low:high]中第k小的元素的算法,其中,1≤k≤high-low+1。

int Search ( int a[], int low, int high, int k ) { 
//在a[low:high]中查找第k小的元素
   if (low==high) return a[low];
   int p = Partition(a, low, high);
   int t = p-low+1if(k<=t) return Search(a,  low,  p,   k );
   else return Search(a, p+1, high,  k-p );
3.6.1复杂度

平均时间复杂度情况下,是Θ(n)
最坏时间复杂度O(n2)

🦄4.书后习题

2-4 大整数乘法的O(nm log(3/2))

在这里插入图片描述
在这里插入图片描述

2-5

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2-27 以中位数为基准的选择问题

在这里插入图片描述
在这里插入图片描述

2-31

在这里插入图片描述
2-8, 2-9, 2-15, 2-16, 2-28

  • 11
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

司六米希

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

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

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

打赏作者

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

抵扣说明:

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

余额充值