算法笔记8

矩阵连乘积

定义:给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2,…n-1。考察这n个矩阵的连乘积A1A2…An

  • 由于矩阵乘法满足结合律,所以计算矩阵的连乘- 可以有许多不同的计算次序。
  • 这种计算次序可以用加括号的方式来确定。
  • 若一个矩阵连乘积的计算次序完全确定,也就是说该连乘积已完全加括号,则可以依此次序反复调用2个矩阵相乘的标准算法计算出矩阵连乘积

完全加括号的矩阵连乘积可递归地定义为:

  1. 单个矩阵是完全加括号的;
  2. 矩阵连乘积A是完全加括号的,则A可表示为2个完全加括号的矩阵连乘积B和C的乘积并加括号,即A=(BC)

设有四个矩阵A, B, C, D,它们的维数分别是:
A=50×10, B=10×40, C=40×30, D=30×5
矩阵A和B可乘的条件: 矩阵A的列数等于矩阵B的行数。
设A是p×q的矩阵, B是q×r的矩阵, 乘积是p×r的矩阵;计算量是pqr。
上述5种完全加括号方式的计算工作量为:

(A((BC)D))(A(B(CD)))((AB)(CD))(((AB)C)D)((A(BC)D))
1600010500360008750034500

BC: 10×40×30 = 12000,
(BC)D: 10×30×5 = 1500,
(A((BC)D)): 50×10×5 = 2500

给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2…,n-1。如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少?

  • 穷举法:列举出所有可能的计算次序,并计算出每一种计算次序相应需要的数乘次数,从中找出一种数乘次数最少的计算次序。

算法复杂度分析:
对于n个矩阵的连乘积,设其不同的计算次序为P(n)。
由于每种加括号方式都可以分解为两个子矩阵的加括号问题:(A1…Ak)(Ak+1…An)可以得到关于P(n)的递推式如下:
在这里插入图片描述

最优解的结构

将矩阵连乘积AiAi+1…Aj 简记为A[i:j], 这里i≤j;
考察计算A[1:n]的最优计算次序。

  • 设这个计算次序在矩阵Ak和Ak+1之间将矩阵链断开,1≤k<n,则其相应完全加括号方式为(A1A2…Ak)(Ak+1Ak+2…An)
  • 计算量:A[1:k]的计算量加上A[k+1:n]的计算量,再加上A[1:k]和A[k+1:n]相乘的计算量

特征:计算A[1:n]的最优次序所包含的计算矩阵子链 A[1:k]和A[k+1:n]的次序也是最优的。
矩阵连乘计算次序问题的最优解包含着其子问题的最优解。

  • 这种性质称为最优子结构性质。
  • 问题的最优子结构性质是该问题可用动态规划算法求解的显著特征。

递归关系

设计算A[i: j],1≤i≤j≤n,所需要的最少数乘次数m[i, j],则原问题的最优值为m[1,n]
当i=j时,A[i: j]=Ai,因此,m[i, i]=0,i=1,2,…,n
当i<j 时,
在这里插入图片描述
这里Ai的维数是Pi-1×Pi
在这里插入图片描述
m[i][j]给出了最优值,最优断开位置为k:
在这里插入图片描述
若将对应于m[i, j]的断开位置k记为s[i, j],在计算出最优值m[i, j]后,可递归的由s[i, j]构造出相应的最优解。

最优值

对于1≤i≤j≤n不同的有序对(i, j)对应于不同的子问题。因此,不同子问题的个数最多只有
在这里插入图片描述
递归计算时,许多子问题被重复计算多次。

  • 这也是该问题可用动态规划算法求解的又一显著特征。

用动态规划算法解此问题,可依据其递归式以自底向上的方式进行计算。

  • 在计算过程中,保存已解决的子问题答案。
  • 每个子问题只计算一次,在后面需要时只要简单查一下,从而避免大量的重复计算,最终得到多项式时间的算法。
#define NUM 51
int p[NUM];
int m[NUM][NUM];
int s[NUM][NUM];
void MatrixChain (int n)
{
  for (int i=1;  i<=n;  i++) m[i][i] = 0;
  for (int r=2;  r<=n;  r++)
	for (int i=1;  i<=n-r+1;  i++) 
	{
	  int j=i+r-1; 
	  //计算初值,从i处断开
	  m[i][j] = m[i+1][j]+p[i-1]*p[i]*p[j];
	  s[i][j] = i; 
	  for (int k=i+1;  k<j;  k++) 
	  { 
		int t = m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
		if (t < m[i][j]) {m[i][j] = t; s[i][j] = k;}
	  }
	}
}

最优解

s[i][j]已经存储了构造最优解所需要的足够的信息。
每个部分的最优加括号方式可以根据数组s的相应元素得出。
照此递推下去,最终可以确定A[1:n]的最优完全加括号方式,即构造出问题的一个最优解。

void TraceBack(int i, int j) 
{ 
	if(i==j) printf("A%d", i);
	else 
	{
		printf("(");
		TraceBack(i,s[i][j]); 
		TraceBack(s[i][j]+1,j); 
		printf(")"); 
	}
}

慕课

选最大与最小

  • 输入:集合 L (含n个不等的实数)
  • 输出:L中第 i 小元素

i=1, 称为最小元素
i=n,称为最大元素
位置处在中间的元素,称为中位元素
n为奇数,中位数唯一,i = (n+1)/2
n为偶数,可指定 i = n/2+1

分组算法

伪码
算法 Findmax
输入:n 个数的数组 L
输出:max, k

  1. max<-L[1]
  2. for i<-2 to n do
  3. if max < L[i]
  4. then max<-L[i]
  5. k<-i
  6. return max,k

分治算法

  1. 将数组 L从中间划分为两个子数组 L1 和 L2
  2. 递归地在L1中求最大 max1 和min1
  3. 递归地在L2中求最大max2和min2
  4. max<-max{ max1 , max2}
  5. min<-min{ min1, min2}
    比较次数 3n/2-2

比较次数 :3n/2-2

选第二大

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

通常算法

顺序比较
1.顺序比较找到最大 max
2.从剩下 n-1个数中找最大,就是第二大second

时间复杂度: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 goto 2
  8. max <- 最大数
  9. second <- max的链表中的最大

时间复杂度: n+⌈logn⌉-2

一般选择问题的算法设计

选第 k 小的算法:
• 分治策略
• 确定m*
• 用m*划分数组归约为子问题
• 递归实现

选择问题的算法分析

伪码
算法 Select (S, k)

  1. 将S分5个一组, 共 nM = ⌈n/5⌉ 组
  2. 每组排序,中位数放到集合 M
  3. m* <- Select(M, ⌈ |M|/2⌉ ) //S分A,B,C,D
  4. A,D元素小于m* 放 S1,大于m*放S2
  5. S1 <- S1∪C;S2 <- S2∪B
  6. if k = |S1| + 1 then 输出 m*
  7. else if k<=|S1|
  8. then Select (S1, k)
  9. else Select (S2, k-|S1|-1)

时间复杂度: Θ(nlogn)

卷积及应用

在这里插入图片描述

在这里插入图片描述

卷积计算

在这里插入图片描述

快速傅立叶变换FF

在这里插入图片描述

平面点集的凸包

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

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值