南开大学软件学院2021年秋季学期研究生算法课程(复习)贪心分治之分治(包含快速傅里叶变换)

状态空间中的算法

状态空间:状态(点)+状态转移(边)+价值函数(点权

  • 求解过程的抽象模型
  • 暴力搜索动态规划都是一类算法框架(或算法思想),本质都是在状态空间中寻找解
  • 二者都需要准确地用最少的状态变量建模
  • 而对于动态规划,还需要定义正确的价值函数和转移更新

分治:子问题互不重叠,但最优子结构需考虑全部子问题

贪心:子问题互不重叠,但最优子结构仅考虑极少子问题

若认为动态规划算法的状态空间是有向无环图的话,对于分治和贪心,其状态空间通常可以建模成,分治需要评估整个树,贪心则是树上的几条链

分治与贪心

经典算法回顾

归并排序:用两个子状态的解构造按序拼接当前状态的解,分治算法,时间复杂度O(n logn)

逆序对个数:用两个子状态的解构造统计个数当前状态的解,分治算法,时间复杂度O(n logn)

快速排序:需用两个子状态的解构造按序拼接当前状态的解,分治算法,期望时间复杂度O(n logn)

第k大数:仅需某一个子状态的解即可,贪心算法,期望时间复杂度O(n)

矩阵快速幂:两个子状态的解相同,贪心算法,时间复杂度O(logn)

分治

Strassen矩阵乘法

给出矩阵A,B\in \mathbb{R}^{n\times n},求C=A\times B

  • 直接乘法的时间复杂度O(n^3)
  • Strassen乘法的核心思想:分块矩阵
    • A=\begin{pmatrix} A_{11} & A_{12} \\ A_{21} & A_{22} \end{pmatrix}B=\begin{pmatrix} B_{11} & B_{12}\\ B_{21} & B_{22} \end{pmatrix}C=\begin{pmatrix} C_{11} & C_{12}\\ C_{21} & C_{22} \end{pmatrix}
  • Strassen算法会复用分块矩阵乘法结果,先10次加法计算:
    • S_1=B_{12}-B_{22}\ S_2=A_{11}+A_{12}\ S_3=A_{21}+A_{22}\ S_4=B_{21}-B_{11}
    • S_5=A_{11}+A_{22}\ S_6=B_{11}+B_{22}\ S_7=A_{12}-A_{22}
    • S_8=B_{21}+B_{22}\ S_9=A_{11}-A_{21}\ S_{10}=B_{11}+B_{12}
  • 再用7次乘法计算:
    • P_1=A_{11}S_1\ P_2=S_2B_{22}\ P_3=S_3B_{11}\ P_4=A_{22}S_4
    • P_5=S_5S_6\ P_6=S_7S_8\ P_7=S_9S_{10}
  • 最终使用8次加法得出结果:
    • C_{11}=P_5+P_4-P_2+P_6\ C_{12}=P_1+P_2
    • C_{21}=P_3+P_4\ C_{22}=P_5+P_1-P_3-P_7
  • 时间复杂度?T(n)=7T(\frac{n}{2})+O(n^2)

分治算法的时间复杂度:T(n)=aT(n/b)+O(n^d)

主定理

  • if\ d>\log_ba,T(n)=O(n^d)
  • if\ d=\log_ba,T(n)=O(n^d\log_ba)
  • if\ d<\log_ba,T(n)=O(n^{\log_ba})

一维数值积分

给出一维函数f(x),计算\int_{a}^{b}f(x)dx(无闭式解)

  • 梯形近似法:将区间等分n份,求n个梯形的面积和
  • 对于区间\left ( x_0,x_1 \right ),其梯形面积等价于过点(x_0,f(x_0))(x_1,f(x_1))线性函数P(x)积分\int_{x_0}^{x_1}P(x)dx
    • P(x)=f(x_0)+\frac{f(x_1)-f(x_0)}{x_1-x_0}(x-x_0)=f(x_0)\frac{x-x_1}{x_0-x_1} +f(x_1)\frac{x-x_0}{x_1-x_0}
    • \int_{x_0}^{x_1}P(x)dx=\frac{x_1-x_0}{2}(f(x_0)+f(x_1))
  • 过2个点的线性函数P(x)线性插值(一次插值)

一维数值积分

给出一维函数f(x),计算\int_{a}^{b}f(x)dx(无闭式解)

  • 插值interpolation 拉格朗日插值多项式
    • n+1个不同的点(x_i,y_i),可确定n阶多项式函数的全部系数
    • A(x)=\sum_{i=0}^{n-1}f(x_i)\prod_{j\neq i}\frac{(x-x_j)}{(x_i-x_j)}
  • 梯形法即为一次插值(但是近似程度不够
  • 优化一:利用二次插值(利用a,m=(a+b)/2,b三个点)
    • P(x)=f(a)\frac{(x-m)(x-b)}{(a-m)(a-b)}+f(m)\frac{(x-a)(x-b)}{(m-a)(m-b)}+f(b)\frac{(x-a)(x-m)}{(b-a)(b-m)}
    • 数值积分转化为下式(即辛普森积分法
    • \int_{a}^{b}f(x)dx\approx \int_{a}^{b}P(x)dx=\frac{b-a}{6}(f(a)+4f(\frac{a+b}{2})+f(b))

一维数值积分

给出一维函数f(x),计算\int_{a}^{b}f(x)dx(无闭式解)

  • 梯形近似法:将区间等分n份,求n个梯形的面积和
  • 思考:分到多细为止?等分是否有问题?

 

  • 显然,每个区间不必分解到相同粒度,但分解后结果要使得积分值在误差范围\varepsilon
  • 优化二:自适应辛普森算法----自适应算法也是一类算法框架
    • AdaSimp(a,b,S(a,b,f)),其中S()为辛普森积分函数
    1. m\leftarrow \frac{a+b}{2}
    2. 计算S(a,m,f)和S(m,b,f)
    3. \left | S(a,m,f)+S(m,b,f)-S(a,b,f) \right |<\varepsilon,则返回S(a,b,f)
    4. 否则,返回AdaSimp(a,m,S(a,m,f))+AdaSimp(m,b,S(m,b,f))
  • 时间复杂度?取决于f(x)的性质和\varepsilon的大小
  • 思考:高维积分这种方法还可行吗?不可行的话该怎么办?

多项式算法

n阶多项式A(x)的定义为

A(x)=\sum_{i=0}^{n-1}a_ix^i=a_0+a_1x+a_2x^2+\cdot \cdot \cdot +a_nx^n

给出两个n阶多项式A(x),B(x),计算C(x)=A(x)✖B(x)

  • 多项式乘法:D(x)=A(x)+B(x)=\sum_{i=0}^{n}d_ix^i,\ where\ d_i=a_i+b_i时间复杂度:O(n)
  • 多项式乘法:C(x)=A(x)\times B(x)=\sum_{i=0}^{2n}c_ix^i,\ where\ c_i=\sum_{k=0}^{i}a_kb_{i-k}时间复杂度:O(n^2)

多项式的表示法

以下对n-1阶多项式A(x)=\sum_{i=0}^{n-1}a_ix^i讨论

  • 系数表示法Coefficient representation
    • 即系数向量\mathbf{a}=(a_0,a_1,\cdot \cdot \cdot ,a_{n-1})即可表示一个多项式
    • 加法时间复杂度O(n),乘法时间复杂度O(n^2)
  • 点值表示法Point-value representation
    • 即使用n个点\left \{ (x_0,y_0),(x_1,y_1),\cdot \cdot \cdot ,(x_n,y_n) \right \}即可表示n-1阶多项式,其中要求y_k=A(x_k),k=0,1,\cdot \cdot \cdot ,n
    • 若对于A(x)的点值表示\left \{ (x_0,y_0),(x_1,y_1),\cdot \cdot \cdot ,(x_n,y_n) \right \}和B(x)的点值表示\left \{ (x_0,y^{'}_0),(x_1,y^{'}_1),\cdot \cdot \cdot ,(x_n,y^{'}_n) \right \}
      • 加法结果为\left \{ (x_0,y_0+y^{'}_0),(x_1,y_1+y^{'}_1),\cdot \cdot \cdot ,(x_n,y_n+y^{'}_n) \right \}复杂度O(n)
      • 乘法结果注意为2n-2阶多项式,需要2n-1个点确定,即为\left \{ (x_0,y_0y^{'}_0),(x_1,y_1y^{'}_1),,\cdot \cdot \cdot (x_{2n-1},y_{2n-1}y^{'}_{2n-1}) \right \}复杂度O(n)

多项式表示法的转换

以下对n-1阶多项式A(x)=\sum_{i=0}^{n-1}a_ix^i讨论

  • 求值Evaluation:系数表示➡点值表示
    • 秦九韶算法/Horner's rule:y_k4=A(x_k)=a_0+x_k(a_1+x_k(a_2+\cdot \cdot \cdot ))
    • 对n个点进行计算,总共需要O(n^2)的时间
  • 插值Interpolation:点值表示➡插值表示
    • ​​​​​​​多项式插值唯一性:范德蒙德矩阵非奇异
    • 拉格朗日插值,时间复杂度O(n^2)
      • ​​​​​​​​​​​​​​A(x)=\sum_{i=0}^{n-1}f(x_i)\prod_{j\neq i}\frac{(x-x_j)}{(x_i-x_j)}

于是,计算乘积C(x)=A(x)\times B(x)可以通过

  • A(x),B(x)系数表示➡系数乘法 O(n^2)➡C(x)系数表示
  • A(x),B(x)系数表示➡求值 O(n^2)➡A(x),B(x)点值表示➡点值乘法 O(n)➡C(x)点值表示➡插值 O(n^2)➡C(x)系数表示

快速傅里叶变换Fast Fourier Transform,FFT

选n个特殊点(x_k,y_k),用分治优化求值和插值O(n logn)

  • A(x),B(x)系数表示➡FFT求值 O(n log n)➡A(x),B(x)点值表示➡点值乘法 O(n)➡C(x)点值表示➡FFT插值 O(n log n)➡C(x)系数表示

特殊的点x_k为第k个n次单位根

背景知识:复变函数 z=a+bi

  • 复数的四则运算:加减乘除
  • 复数的几何表示:复平面,模长r和辐角\theta
  • 运算的几何意义:加:四边形法则;乘:模长乘,辐角加
  • 欧拉公式:e^{\theta i}=\cos \theta+i\sin \theta
  • 单位根:复数域上满足x^n=1所有解:共有n个根,记作
    • w_n^k=e^{\frac{2\pi k}{n}i},\ for\ k=0,1,\cdot \cdot \cdot ,n-1
  • n个单位根构成了循环群,生成元(本源根)w_n^1
  • 模n加/乘法群,w_n^jw_n^k=w_n^{(j+k)\ mod\ n}(w_n^k)^i=w_n^{(ki)\ mod\ n}
  • 折半引理:w_{2n}^{2k}=w_n^k
  • 消去引理:w_n^{k+\frac{n}{2}}=-w_n^k
  • 求和引理:\sum_{i=0}^{n-1}(w_n^k)^i=0

离散傅里叶变换Discrete Fourier Transform,DFT

即对n-1阶多项式A(x)在n次单位根上的求值过程

  • 给出A(x)的系数表示,即向量\mathbf{a}=(a_0,a_1,\cdot \cdot \cdot ,a_{n-1}),计算其在n次单位根w_n^k上的值y_k​​​​​​​,即
    • y_k=A(w_n^k)=\sum_{i=0}^{n-1}a_i(w_n^k)^i,for\ k=0,1,\cdot \cdot \cdot ,n-1
  • 在这种情况下,向量\mathbf{y}=(y_0,y_1,\cdot \cdot \cdot ,y_{n-1})即为系数向量\mathbf{a}=(a_0,a_1,\cdot \cdot \cdot ,a_{n-1})离散傅里叶变换,记作
    • \mathbf{y}=DFT(\mathbf{a})或者\mathbf{a}=DFT^{-1}(\mathbf{y})
  • 由单位根w_n^k的特殊性质,DFT可用分治快速完成➡FFT

快速傅里叶变化(求值部分)

  • 首先,假定A(x)的阶数n为2的整数次幂(通过引入0系数高阶项可以永远做到)
  • 分别通过A(x)的奇数次项和偶数次项系数定义新多项式
    • A^{'}(x)=a_0+a_2x+a_4x^2+\cdot \cdot \cdot +a_{n-2}x^{\frac{n}{2}-1} 
    • A^{''}(x)=a_1+a_3x+a_5x^2+\cdot \cdot \cdot +a_{n-1}x^{\frac{n}{2}-1}
  • 由此可得分治算法的关键:A(x)=A^{'}(x^2)+xA^{''}(x^2)
  • 因此,计算A(x)在w_n^0,w_n^1,\cdot \cdot \cdot ,w_n^{n-1}上的值,可以转化为:

     

    • 先计算A^{'}(x)A^{''}(x)(w_n^0)^2,(w_n^1)^2,\cdot \cdot \cdot ,(w_n^{n-1})^2上的值(注意根据折半引理和消去引理可以使计算点的个数减半
    • 再根据A(x)=A^{'}(x^2)+xA^{''}(x^2)合并结果
  • 具体来说,计算A(w_n^0),A(w_n^1),\cdot \cdot \cdot ,A(w_n^{n-1}),可以转化为:
    • 对于k=0,1,\cdot \cdot \cdot ,\frac{n}{2}-1前n/2个点
    • A(w_n^k)=A^{'}((w_n^k)^2)+w_n^kA^{''}((w_n^k)^2)=A^{'}(w_{\frac{n}{2}}^k)+w_n^kA^{''}(w_{\frac{n}{2}}^k)
    • 对于k+\frac{n}{2}=\frac{n}{2},\frac{n}{2}+1,\cdot \cdot \cdot ,n-1(后n/2个点,但k=0,1,\cdot \cdot \cdot ,\frac{n}{2}-1)
    • A(w_n^{k+\frac{n}{2}})=A^{'}(w_n^{2k+n})+w_n^{k+\frac{n}{2}}A^{''}(w_n^{2k+n})=A^{'}(w_{\frac{n}{2}}^k)-w_n^kA^{''}(w_{\frac{n}{2}}^k)
  •  总结来说,A(x)上的n次单位根的值,只需分别计算一遍A^{'}(x)A^{''}(x)n/2次单位根值即可构造出来
  • 时间复杂度?T(n)=2T(\frac{n}{2})+O(n)=O(n\log n)

快速傅里叶变换(插值部分)

  • 注意,离散傅里叶变换 \mathbf{y}=DFT(\mathbf{a})其实可以写成矩阵形式\mathbf{y}=V_n\mathbf{a},其中V_n范德蒙德矩阵,第k行第j列元素为w_n^{kj}
  • 于是,\mathbf{a}=DFT^{-1}(\mathbf{y})也就是\mathbf{a}=V_n^{-1}\mathbf{y},由范德蒙德矩阵的求逆公式,第k行第j列元素为\frac{w_n^{-kj}}{n}
  • 因此,插值部分即将\mathbf{y}=(y_0,y_1,\cdot \cdot \cdot ,y_{n-1})视作系数向量,构成新多项式,计算其在w_n^0,w_n^{-1},\cdot \cdot \cdot ,w_n^{-(n-1)}上的值,所得向量结果除上n即得到答案,此过程同理亦可分治

分治算法小结

  • 难点:综合所有子问题的解构造问题的解的过程
  • 特点:时间复杂度通常使用主定理计算
  • 思维特点:
  1. 子问题规模要成倍缩小;(分解
  2. 假设子问题完成,如何得出原问题的答案;(合并
  • 更多:平面最近点对、CDQ分治、并行分布式的Map-Reduce

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值