【浅记】分而治之

news2024/11/27 5:37:57

归并排序

算法流程:

  1. 将数组A[1,n]排序问题分解为A[1,n/2]A[n/2+1,n]排序问题
  2. 递归解决子问题得到两个有序的子数组
  3. 将两个子数组合并为一个有序数组

符合分而治之的思想:

  1. 分解原问题
  2. 解决子问题
  3. 合并问题解

递归式求解

递归树法

用树的形式表示抽象递归

T ( n ) = { 2 T ( n 2 ) + O ( n ) , i f n > 1 O ( 1 ) , i f n = 1 T(n)=\begin{cases} 2T(\frac{n}{2})+O(n), &if&n>1\\ O(1),&if&n=1 \end{cases} T(n)={2T(2n)+O(n),O(1),ififn>1n=1

树的深度通常从0开始计,故层数等于n+1,后续统一用深度
可以得到,这个算法的时间复杂度是: T ( n ) = O ( n log ⁡ n ) T(n)=O(n\log n) T(n)=O(nlogn)

主定理法

对形如 T ( n ) = a T ( n b ) + f ( n ) T(n)=aT(\frac{n}{b})+f(n) T(n)=aT(bn)+f(n)的递归式:

  • 每个节点共a个分支
  • 每层以因子b速度下降
  • n log ⁡ b a n^{\log_ba} nlogba代表每层叶子节点代价之和

可以得到如下公式:
KaTeX parse error: {align} can be used only in display mode.
f ( n ) f(n) f(n)形式为 n k n^k nk时,可简化主定理公式:
KaTeX parse error: {align} can be used only in display mode.
例: T ( n ) = 5 T ( n 2 ) + n 3 T(n)=5T(\frac{n}{2})+n^3 T(n)=5T(2n)+n3

  1. k = 3 k=3 k=3
  2. a = 5 , b = 2 , log ⁡ b a = log ⁡ 2 5 a=5,b=2,\log_ba=\log_25 a=5,b=2,logba=log25
  3. k > log ⁡ b a k>\log_ba k>logba
  4. T ( n ) = Θ ( n 3 ) T(n)=\Theta(n^3) T(n)=Θ(n3)

最大子数组

基于枚举策略

蛮力枚举:枚举所有可能的情况
枚举 n + C n 2 n+C_n^2 n+Cn2种可能的区间 [ l , r ] , ( l < r ) [l,r],(l<r) [l,r],(l<r),求解最大子数组之和 S m a x S_{max} Smax,时间复杂度为 O ( n 3 ) O(n^3) O(n3)
优化枚举:蛮力枚举存在重复计算
S ( l , r ) = Σ i = 1 r X [ i ] = S ( l , r − 1 ) + X [ r ] S(l,r)=\Sigma_{i=1}^rX[i]=S(l,r-1)+X[r] S(l,r)=Σi=1rX[i]=S(l,r1)+X[r],时间复杂度为 O ( n 2 ) O(n^2) O(n2)

分而治之

  1. 将数组 X [ 1.. n ] X[1..n] X[1..n]分为 X [ 1.. n / 2 ] X[1..n/2] X[1..n/2] X [ n / 2 + 1.. n ] X[n/2+1..n] X[n/2+1..n]
  2. 递归求解子问题:
    1. S 1 S_1 S1:数组 X [ 1.. n / 2 ] X[1..n/2] X[1..n/2]的最大子数组
    2. S 2 S_2 S2:数组 X [ n / 2 + 1.. n ] X[n/2+1..n] X[n/2+1..n]的最大子数组
  3. 合并子问题,得到 S m a x S_{max} Smax
    1. S 3 S_3 S3:跨中点的最大子数组
    2. 数组 X X X的最大子数组之和 S m a x = m a x { S 1 , S 2 , S 3 } S_{max}=max\{S_1,S_2,S_3\} Smax=max{S1,S2,S3}

问题在于,如何高效地求解 S 3 S_3 S3

  1. m i d = n 2 mid=\frac n2 mid=2n
  2. S 3 S_3 S3可以分为左右两部分:
    1. L e f t Left Left:以 X [ m i d ] X[mid] X[mid]为结尾的最大子数组之和
    2. R i g h t Right Right:以 X [ m i d + 1 ] X[mid+1] X[mid+1]为开头的最大子数组之和
    3. S 3 = L e f t + R i g h t S_3=Left+Right S3=Left+Right

求解 S 3 S_3 S3的时间复杂度分析:

  1. 求解 L e f t Left Left:从 X [ m i d ] X[mid] X[mid]向前遍历求和,并记录最大值,时间复杂度为 O ( m i d ) O(mid) O(mid)
  2. 求解 R i g h t Right Right:从 X [ m i d + 1 ] X[mid+1] X[mid+1]向后遍历求和,并记录最大值,时间复杂度为 O ( n − m i d ) O(n-mid) O(nmid)
  3. 求解 S 3 S_3 S3的时间复杂度: O ( n ) O(n) O(n)

伪代码:

输入:数组X,数组下标low,high
输出:最大子数组之和Smax
if low=high then
|	return X[low]
end
else
|	mid	<-	(low+high)/2
|	S1	<-	MaxSubArray(X,low,mid)
|	S2	<-	MaxSubArray(X,mid+1,high)
|	S3	<-	CrossingSubArray(X,low,mid,high)
|	Smax	<-	Max(S1,S2,S3)
|	return Smax
end

时间复杂度分析

$T(n)=
\left{
\begin{align}
&1,\quad&n=1\
&2T(\frac n2)+O(n),\quad&n>1
\end{align}
\right.
\$
按照上面提到的递归树求解的方法,可以得到: T ( n ) = n log ⁡ n T(n)=n\log n T(n)=nlogn

逆序对计数

逆序对:当 i < j i<j i<j A [ i ] > A [ j ] A[i]>A[j] A[i]>A[j]的二元组 ( A [ i ] , A [ j ] ) (A[i],A[j]) (A[i],A[j])

蛮力枚举

对于数组的每个元素 A [ i ] A[i] A[i],枚举 j ( j > i ) j(j>i) j(j>i),并统计逆序对数目。
伪代码:

输入:一个大小为n的数组A[1..n]
输出:数组A[1..n]中逆序对数目Sum
Sum	<-	0
for i <- 1 to n do
|	for j <- i+1 to n do
|	 |	if A[i]>A[j] then
|	 |	|	Sum <- Sum+1
|	 |	end
|	end
end
return Sum

这一算法时间复杂度为 O ( n 2 ) O(n^2) O(n2)

分而治之

  1. 将数组 A [ 1.. n ] A[1..n] A[1..n]分为 A [ 1.. n 2 ] A[1..\frac n2] A[1..2n] A [ n 2 + 1.. n ] A[\frac n2+1..n] A[2n+1..n]
  2. 递归求解子问题
    1. S 1 S_1 S1:仅在 A [ 1.. n 2 ] A[1..\frac n2] A[1..2n]中的逆序对数目
    2. S 2 S_2 S2:仅在 A [ n 2 + 1.. n ] A[\frac n2+1..n] A[2n+1..n]中的逆序对数目
  3. 合并 A [ 1.. n ] A[1..n] A[1..n]分为 A [ 1.. n 2 ] A[1..\frac n2] A[1..2n] A [ n 2 + 1.. n ] A[\frac n2+1..n] A[2n+1..n]的解
    1. S 3 S_3 S3:跨越子数组的逆序对数目
    2. S = S 1 + S 2 + S 3 S=S_1+S_2+S_3 S=S1+S2+S3

策略一:直接求解

对每个 A [ j ] ∈ A [ m + 1 , n ] A[j]\in A[m+1,n] A[j]A[m+1,n],枚举 A [ i ] ∈ A [ 1.. m ] A[i]\in A[1..m] A[i]A[1..m]并统计逆序对数目。
求解 S 3 S_3 S3的算法运行时间: O ( n 2 ) O(n^2) O(n2)
分而治之框架的运行时间: T ( n ) = 2 T ( n 2 ) + O ( n 2 ) T(n)=2T(\frac n2)+O(n^2) T(n)=2T(2n)+O(n2)
直接求解的分而治之较蛮力枚举并未提高算法运行时间。

  • 运行时间受制于跨越子数组的逆序对计数方法
  • 数组的有序性通常有助于提高算法的运行时间

策略二:排序求解

  1. 分别对数组 A [ 1.. m ] A[1..m] A[1..m] A [ m + 1.. n ] A[m+1..n] A[m+1..n]进行排序
  2. 对于每个 A [ j ] ∈ A [ m + 1.. n ] A[j]\in A[m+1..n] A[j]A[m+1..n],采用二分查找为其在 A [ 1.. m ] A[1..m] A[1..m]中定位
  3. A [ j ] A[j] A[j] A [ 1.. m ] A[1..m] A[1..m]定位点右侧的元素均可与 A [ j ] A[j] A[j]构成逆序对

求解 S 3 S_3 S3的算法运行时间: O ( n log ⁡ 2 n ) O(n\log^2 n) O(nlog2n)
分治框架的算法运行时间: T ( n ) = 2 T ( n 2 ) + O ( n log ⁡ n ) T(n)=2T(\frac n2)+O(n\log n) T(n)=2T(2n)+O(nlogn)

算法优化

合并问题解的同时对数组进行排序

  • 归并过程中可同时计算逆序对数目

策略三:归并求解

  1. 从左到右扫描有序子数组: A [ i ] ∈ A [ 1.. m ] , A [ j ] ∈ A [ m + 1.. n ] A[i]\in A[1..m],A[j]\in A[m+1..n] A[i]A[1..m],A[j]A[m+1..n]
    1. 如果 A [ i ] > A [ j ] A[i]>A[j] A[i]>A[j],统计逆序对, j j j向右移
    2. 如果 A [ i ] < A [ j ] A[i]<A[j] A[i]<A[j] i i i向右移
  2. 利用归并排序框架保证合并后数组的有序性

伪代码:

输入:数组A[1..n],数组下标left,right
输出:数组A[left..right]的逆序对数,递增数组A[left..right]
if left >= right then
|	return A[left..right]
end
mid	<-(left+right)/2
S1	<- CountInver(A,left,mid)
S2	<- CountInver(A,mid+1,right)
S3	<- MergeCount(A,left,mid,right)
S		<- S1+S2+S3
return S,A[left..right]

时间复杂度: T ( n ) = O ( n log ⁡ n ) T(n)=O(n\log n) T(n)=O(nlogn)

快速排序

归并排序:简化分解,侧重合并
快速排序:侧重分解,简化合并

数组划分

  1. 任选 x x x作为分界线,称为主元
  2. 交换重排,满足 x x x左侧元素小于右侧

实现方法:

  1. 选取固定位置主元 x x x,如尾元素
  2. 维护两个指针变量,分别指向两个部分的右端点
  3. 考察数组元素 A [ j ] A[j] A[j],只和主元比较
    1. A [ j ] ≤ x A[j]\leq x A[j]x,则交换 A [ j ] A[j] A[j] A [ i ] + 1 A[i]+1 A[i]+1 i i i j j j右移
    2. A [ j ] > x A[j]> x A[j]>x,则 j j j右移
  4. 把主元放在中间作分界线

伪代码Partition(A,p,r)

输入:数组A,起始位置p,终止位置r
输出:划分位置q
x <- A[r]//选取主元
i <- p-1
for j <- p to r-1 do
 | if A[j] <= x then
 | | exchange A[i+1] with A[j]
 | | i <- i+1
 | end
end
exchange A[i+1] with A[r]
q <- i+1
return q

快速排序的伪代码

输入:数组A,起始位置p,终止位置r
输出:有序数组A
if p<r then
| q <- Partition(A,p,r)
| QuickSort(A,p,q-1)
| QuickSort(A,q+1,r)
end

最好情况: O ( n log ⁡ n ) O(n\log n) O(nlogn)
最坏情况: O ( n 2 ) O(n^2) O(n2)
快速排序看似不优于归并排序。

次序选择问题

输入:

  • 包含 n n n个不同元素的数组 A [ 1.. n ] A[1..n] A[1..n]
  • 整数 k k k

输出:

  • 数组 A [ 1.. n ] A[1..n] A[1..n]中第 k k k小的元素 ( 1 ≤ k ≤ n ) (1\leq k\leq n) (1kn)

固定位置划分求解

image.png
选取固定位置主元,小于主元的元素个数 q − p q-p qp

  • 情况1: k = q − p + 1 k=q-p+1 k=qp+1 A [ q ] A[q] A[q]为数组第 k k k小元素
  • 情况2: k < q − p + 1 k<q-p+1 k<qp+1,在 A [ p . . q − 1 ] A[p..q-1] A[p..q1]中寻找第 k k k小元素
  • 情况3: k > q − p + 1 k>q-p+1 k>qp+1,在 A [ q + 1.. r ] A[q+1..r] A[q+1..r]中寻找第 k − ( q − p + 1 ) k-(q-p+1) k(qp+1)小元素

子问题始终唯一,无需合并问题解。

伪代码

输入:数组A,起始位置p,终止位置r,元素次序k
输出:第k小元素x
q <- Partition(A,p,r)
if k=(q-p+1) then
| x <- A[q]
end
if k<(q-p+1) then
| x <-Selection(A,p,q-1,k)
end
if k>(q-p+1) then
| x <- Selection(A,q+1,r,k-(q-p+1))
end
return x

复杂度分析:
最好情况: T ( n ) = Ω ( n ) T(n)=\Omega(n) T(n)=Ω(n)
期望时间复杂度: T ( n ) = Θ ( n ) T(n)=\Theta(n) T(n)=Θ(n)
最坏情况: T ( n ) = O ( n 2 ) T(n)=O(n^2) T(n)=O(n2)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1056118.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JAVA面经整理(4)

一)Volitaile关键字的作用: volatile的使用:常常用于一写多读的情况下&#xff0c;解决内存可见性和指令重排序 JAVA内存的JMM模型:主要是用来屏蔽不同硬件和操作系统的内存访问差异的&#xff0c;在不同的硬件和不同的操作系统内存的访问是有差异的&#xff0c;这种差异会导致…

C. Best Binary String

题目&#xff1a;样例&#xff1a; 输入 4 ??01? 10100 1??10? 0?1?10?10输出 00011 10100 111101 011110010 思路&#xff1a; 根据题意&#xff0c; 题目意思是 ‘&#xff1f;’ 字符 该替换何值&#xff0c;使得原字符串&#xff0c;最少操作 翻转任意区间&#…

贪心算法+练习

正值国庆之际&#xff0c;祝愿祖国繁荣昌盛&#xff0c;祝愿朋友一生平安&#xff01;终身学习&#xff0c;奋斗不息&#xff01; 目录 1.贪心算法简介 2.贪心算法的特点 3.如何学习贪心算法 题目练习&#xff08;持续更新&#xff09; 1.柠檬水找零&#xff08;easy&…

QT:鼠标画线(双画布)

widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPoint> //点 #include <QMouseEvent> //鼠标事件 #include <QPaintEvent> //绘图事件class Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent 0);~Wi…

论文笔记:TMN: Trajectory Matching Networks for PredictingSimilarity

2022 ICDE 1 intro 1.1 背景 轨迹相似度可以划分为&#xff1a; 非学习度量方法 通常是为一两个特定的轨迹距离度量设计的&#xff0c;因此不能与其他度量一起使用通常需要二次时间&#xff08;O(n^2)&#xff09;来计算轨迹之间的精确距离基于学习的度量方法 利用机器学习…

第一届“龙信杯”取证

案情简介 2023年9月&#xff0c;某公安机关指挥中心接受害人报案&#xff1a;通过即时通讯工具添加认识一位叫“周微”的女人&#xff0c;两人谈论甚欢&#xff0c;确定网上恋爱关系&#xff0c;后邀约裸聊&#xff0c;受害人上钩后&#xff0c;“周微”和受害人进行裸聊&#…

Kafka集群架构设计原理详解

文章目录 1、zookeeper整体数据2、Controller Broker选举机制 1、zookeeper整体数据 Kafka将状态信息保存在Zookeeper中&#xff0c;这些状态信息记录了每个Kafka的Broker服务与另外的Broker服务有什么不同。通过这些差异化的功能&#xff0c;共同体现出集群化的业务能力。这些…

SpringCloud Alibaba - Sentinel 授权规则、自定义异常结果

目录 一、授权规则 1.1、什么是授权规则 1.2、授权规则的配置 1.2.1、配置信息介绍 1.2.2、如何得到请求来源 1.2.3、实现步骤 a&#xff09;给网关过来的请求添加请求头信息 b&#xff09;在 订单微服务 中实现 RequestOriginParser 接口中的 parseOrigin 方法 c&…

【JAVA】普通IO数据拷贝次数的问题探讨

最近看到网上有些文章在讨论JAVA中普通文件IO读/写的时候经过了几次数据拷贝&#xff0c;如果从系统调用开始分析&#xff0c;以读取文件为例&#xff0c;数据的读取过程如下&#xff08;以缓存I/O为例&#xff09;&#xff1a; 应用程序调用read函数发起系统调用&#xff0c;此…

1574. 删除最短的子数组使剩余数组有序

1574. 删除最短的子数组使剩余数组有序 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a; 原题链接&#xff1a; 1574. 删除最短的子数组使剩余数组有序 https://leetcode.cn/problems/shortest-subarray-to-be-removed-to-make-array-so…

竞赛选题 机器视觉 opencv 深度学习 驾驶人脸疲劳检测系统 -python

文章目录 0 前言1 课题背景2 Dlib人脸识别2.1 简介2.2 Dlib优点2.3 相关代码2.4 人脸数据库2.5 人脸录入加识别效果 3 疲劳检测算法3.1 眼睛检测算法3.2 打哈欠检测算法3.3 点头检测算法 4 PyQt54.1 简介4.2相关界面代码 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#x…

redis runtime error: invalid memory address or nil pointer dereference

var Conn redis.Connfunc RedisInit(){Conn, err redis.Dial("tcp", "127.0.0.1:6379")if err ! nil {fmt.Println("redis.Dial err", err)return}fmt.Println("conn suc.11..", Conn)//defer Conn.Close()看看这两段代码的区别 而且…

游戏报错提示d3dx9_43.dll丢失怎么解决?这4个解决方法可以解决

随着科技的发展&#xff0c;电脑已经成为我们生活中不可或缺的一部分。然而&#xff0c;在使用电脑的过程中&#xff0c;我们可能会遇到各种问题&#xff0c;其中之一就是“d3dx9_43.dll丢失”。这个问题可能会影响到我们的电脑性能&#xff0c;甚至导致一些软件无法正常运行。…

管理经济学基本概念(三): 制定战略、竞争优势、员工利益等

1、怎么制定战略才能具备可持续的竞争优势 1.1、什么是可持续的竞争优势&#xff1f; 拥有以下两点&#xff0c;厂商就有了一种竞争优势&#xff0c;具有竞争优势的厂商能够赚取正值的经济利润&#xff1a; 以更低的成本像竞争对手一样提供相同的产品或服务效益 以相同的成本…

使用华为eNSP组网试验⑷-OSPF多区域组网

今天进行了OSPF的多区域组网试验&#xff0c;本来这是个很简单的操作&#xff0c;折腾了好长时间&#xff0c;根本原因只是看了别人写的配置代码&#xff0c;没有真正弄明白里面对应的规则。 一般情况下&#xff0c;很多单位都使用OSPF进行多区域的组网&#xff0c;大体分为1个…

[React] Zustand状态管理库

文章目录 1.Zustand介绍2.创建一个store3.使用方法3.1 获取状态3.2 更新状态3.3 访问存储状态3.4 处理异步数据3.5 在状态中访问和存储数组3.6 持续状态 4.总结 1.Zustand介绍 状态管理一直是现代程序应用中的重要组成部分, Zustand使用 hooks 来管理状态无需样板代码。 更少…

2023腾讯云服务器优惠价格表_10月更新报价

阿里云服务器10月报价表来了&#xff0c;和9月份价格差不多&#xff0c;再等一个月就到腾讯云双十一优惠活动了&#xff0c;腾讯云百科先来说说10月腾讯云服务器优惠价格表&#xff1a;轻量应用服务器2核2G3M带宽95元一年、2核4G5M带宽218元一年、2核2G4M带宽三年价540元一年、…

多头注意力机制

前面已经讲完了自注意力机制&#xff0c;简单来讲&#xff0c;就是对一组向量空间分别求内积&#xff0c;然后进行缩放&#xff0c;最后对不同的向量使用压缩后的分数累加求和。 1.多头是个什么东西&#xff1f; 实际上很简单&#xff0c;自注意力层的输出空间被分解为一组独立…

(ubuntu)Docker 安装linux 详情过程

文章目录 前言Docker 安装linux第一步&#xff1a;使用dokcker 拉取镜像&#xff1a;第二步&#xff1a;创建本地目录&#xff08;用于挂载&#xff09;第三步&#xff1a;&#xff08;上传配置文件&#xff09;修改配置文件第四步&#xff1a;创建docker容器第五步: 测试本地连…

检测防火墙是否开启、判断程序是否加入防火墙白名单(附源码)

VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&#xff09;https://blog.csdn.net/chenlycly/article/details/124272585C软件异常排查从入门到精通系列教程&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&a…