【算法】分治算法(第三章习题解答)

news2024/9/28 3:10:29

3 分治算法

在这里插入图片描述

3.1

A A A n n n 个非 0 0 0 实数构成的数组, 设计一个算法重新排列数组中的数, 使得负数都排在正数前面. 要求算法使用 O ( n ) O(n) O(n) 的时间和 O ( 1 ) O(1) O(1) 的空间.

算法设计:由于算法要求使用 O ( n ) O(n) O(n) 的时间和 O ( 1 ) O(1) O(1) 的空间,因此可以使用类似快速排序的方式将数组扫描一遍完成局部排序。而且已知 A A A中只有正数和负数,因此如果以比较作为基本运算,比较的对象就是 0 0 0,相当于对 A A A进行一轮哨兵元素为 0 0 0的快速排序。

数据输入: A [ 1.. n ] A[1 . . n] A[1..n]

结果输出:排序好的 A [ 1.. n ] A[1 . . n] A[1..n]

伪码描述:

  1. p ← 1 / / 从起始位置向后扫描的指针 p \leftarrow 1 \quad / / 从起始位置向后扫描的指针 p1//从起始位置向后扫描的指针
  2. q ← n / / 从末尾位置向前扫描的指针 q \leftarrow n \quad / / 从末尾位置向前扫描的指针 qn//从末尾位置向前扫描的指针
  3. w h i l e    A [ p ] < 0    a n d    p < n    d o / / 直到找到第一个正数 while\ \ A[p]<0\ \ and \ \ p<n\ \ do \quad //直到找到第一个正数 while  A[p]<0  and  p<n  do//直到找到第一个正数
  4. p ← p + 1 p \leftarrow p+1 pp+1
  5. w h i l e    A [ q ] > 0    a n d    p > 1    d o / / 直到找到第一个负数 while\ \ A[q]>0\ \ and \ \ p>1\ \ do \quad //直到找到第一个负数 while  A[q]>0  and  p>1  do//直到找到第一个负数
  6. q ← q − 1 q \leftarrow q-1 qq1
  7. i f    p < q / / 检查满足交换的条件 if\ \ p<q \quad //检查满足交换的条件 if  p<q//检查满足交换的条件
  8. t h e n   s w a p ( A [ p ] , A [ q ] ) ; g o t o   3 / / 交换两个元素并开始新一轮扫描 then \ swap(A[p], A[q]);goto\ 3\quad//交换两个元素并开始新一轮扫描 then swap(A[p],A[q]);goto 3//交换两个元素并开始新一轮扫描
  9. e l s e   r e t u r n    A / / 排序结束返回 else\ return\ \ A\quad//排序结束返回 else return  A//排序结束返回

复杂度分析:该算法相当于对数组进行一轮哨兵元素为 0 0 0的快速排序,易得算法的时间复杂度是
W ( n ) = O ( n ) \begin{aligned} W(n)=O(n ) \end{aligned} W(n)=O(n)
算法没有空间存储需求,全部操作都在原数组上完成,因此空间复杂度是
S ( n ) = O ( 1 ) \begin{aligned} S(n)=O(1 ) \end{aligned} S(n)=O(1)

3.2

S S S n n n 个不等的正整数集合, n n n 为偶数, 给出一个算法将 S S S 划分为子集 S 1 S_1 S1 S 2 S_2 S2,使得 ∣ S 1 ∣ = ∣ S 2 ∣ = n / 2 |S_1| = |S_2| = n/2 S1=S2=n/2, 且 ∣ ∑ x ∈ S 1 x − ∑ x ∈ S 2 x ∣ | ∑ _{x∈S_1} x − ∑ _{x∈S_2} x| xS1xxS2x 达到最大, 即使得两个子集元素之和的差达到最大.

算法设计: n n n个不等的正整数集合 S S S的元素个数为偶数,因此 n / 2 n/2 n/2仍为整数,划分后 ∣ S 1 ∣ = ∣ S 2 ∣ = n / 2 |S_1| = |S_2| = n/2 S1=S2=n/2,要想使得 ∣ ∑ x ∈ S 1 x − ∑ x ∈ S 2 x ∣ | ∑ _{x∈S_1} x − ∑ _{x∈S_2} x| xS1xxS2x 达到最大,就需要找出这个集合中较大或者较小的 n / 2 n/2 n/2个数,一种简易的思路就是先对集合 S S S进行排序,排好序后直接按索引将前 n / 2 n/2 n/2个数划分出来作为目标子集即可达到目的。

数据输入: S [ 1.. n ] S[1 . . n] S[1..n]

结果输出: S 1 [ 1.. n / 2 ] , S 2 [ 1.. n / 2 ] S_1[1..n/2], S_2[1..n/2] S1[1..n/2],S2[1..n/2]

伪码描述:

  1. L ← Sort ⁡ ( S ) / / 先对集合 S 使用排序算法进行排序得到数组 L L \leftarrow \operatorname{Sort}(S) \quad / / 先对集合S使用排序算法进行排序得到数组L LSort(S)//先对集合S使用排序算法进行排序得到数组L
  2. S 1 ← L [ 1.. n / 2 ] / / 划分排序后的数组的到子集 S 1 S_1 \leftarrow L[1..n/2] \quad / / 划分排序后的数组的到子集S_1 S1L[1..n/2]//划分排序后的数组的到子集S1
  3. S 2 ← L [ n / 2.. n ] / / 划分排序后的数组的到子集 S 2 S_2 \leftarrow L[n/2..n] \quad / / 划分排序后的数组的到子集S_2 S2L[n/2..n]//划分排序后的数组的到子集S2
  4. r e t u r n    S 1 , S 2 / / 返回划分好的两个子集 return\ \ S_1, S_2\quad//返回划分好的两个子集 return  S1,S2//返回划分好的两个子集

复杂度分析:该算法的时间代价集中在第 1 1 1行的排序算法的环节,排序的时间复杂度为 O ( n log ⁡ n ) O(n \log n) O(nlogn),之后的数组划分部分时间复杂度为 O ( 1 ) O(1 ) O(1),因此该算法的总时间复杂度为
W ( n ) = O ( n log ⁡ n ) + O ( 1 ) = O ( n log ⁡ n ) \begin{aligned} W(n)=O(n \log n)+O(1 )=O(n \log n) \end{aligned} W(n)=O(nlogn)+O(1)=O(nlogn)

默认排序算法都在原数组上完成,因此算法只需要常数规模的存储空间,空间复杂度是
S ( n ) = O ( 1 ) \begin{aligned} S(n)=O(1 ) \end{aligned} S(n)=O(1)

3.3

A A A B B B 都是从小到大已经排好序的 n n n 个不等的整数构成的数组, 如果把 A A A B B B 合并后的数组记作 C C C, 设计一个算法找出 C C C 的中位数并给出复杂度分析.

算法设计:第一时间想到的思路是直接对 A A A B B B进行顺序遍历同时比较大小,找到第 n n n个数返回,这相当于将 C C C进行了排序,但是题目只需要我们给出 C C C的中位数即可,显然这样的算法并不是最优解。

因此不妨采用递归分治的思想,并采用类似二分查找的方式寻找中位数,具体操作即将 A A A B B B的中位数拿出比较,如果二者相等则就是 C C C的中位数,如果不相等,则根据具体情况递归查询规模减半的 A A A B B B的一半子集。

数据输入: A [ 1.. n ] , B [ 1.. n ] A[1 . . n],B[1 . . n] A[1..n],B[1..n]

结果输出: C C C的中位数 m e d i a n median median

伪码描述:

f i n d M e d i a n   ( A , B , s t a r t 1 , e n d 1 , s t a r t 2 , e n d 2 ) : findMedian\ (A, B, start1,end1,start2,end2): findMedian (A,B,start1,end1,start2,end2):

  1. m i d 1 ← ( s t a r t 1 + e n d 1 ) / 2 / / 找到 A 的中间元素索引值 mid1 \leftarrow (start1+end1)/2 \quad / / 找到A的中间元素索引值 mid1(start1+end1)/2//找到A的中间元素索引值
  2. m i d 2 ← ( s t a r t 2 + e n d 2 ) / 2 / / 找到 B 的中间元素索引值 mid2 \leftarrow (start2+end2)/2 \quad / / 找到B的中间元素索引值 mid2(start2+end2)/2//找到B的中间元素索引值
  3. i f    A [ m i d 1 ] = B [ m i d 2 ] / / 判断是否为中位数 if\ \ A[mid1]=B[mid2]\quad //判断是否为中位数 if  A[mid1]=B[mid2]//判断是否为中位数
  4. t h e n   r e t u r n   A [ m i d 1 ] / / 找到峰顶返回 then \ return \ A[mid1]\quad//找到峰顶返回 then return A[mid1]//找到峰顶返回
  5. i f    A [ m i d 1 ] < B [ m i d 2 ] / / 峰顶在后半部分 if\ \ A[mid1]<B[mid2] \quad //峰顶在后半部分 if  A[mid1]<B[mid2]//峰顶在后半部分
  6. t h e n   f i n d M e d i a n   ( A , B , m i d 1 , e n d 1 , s t a r t 2 , m i d 2 ) / / 递归寻找 then \ findMedian\ (A, B, mid1,end1,start2,mid2)\quad//递归寻找 then findMedian (A,B,mid1,end1,start2,mid2)//递归寻找
  7. i f    A [ m i d 1 ] > B [ m i d 2 ] / / 峰顶在前半部分 if\ \ A[mid1]>B[mid2] \quad //峰顶在前半部分 if  A[mid1]>B[mid2]//峰顶在前半部分
  8. t h e n   f i n d M e d i a n   ( A , B , s t a r t 1 , m i d 1 , m i d 2 , e n d 2 ) / / 递归寻找 then \ findMedian\ (A, B, start1,mid1,mid2,end2)\quad//递归寻找 then findMedian (A,B,start1,mid1,mid2,end2)//递归寻找

递推方程:
{ W ( n ) = W ( n 2 ) + 1 W ( 1 ) = 1 \left\{\begin{array}{l} W(n)=W\left(\frac{n}{2}\right)+1 \\ W(1)=1 \end{array}\right. {W(n)=W(2n)+1W(1)=1
复杂度分析:该算法使用递归分治的思想,由递推方程可知,每次递归问题的规模减半,因此易得算法的时间复杂度是
W ( n ) = O ( log ⁡ n ) \begin{aligned} W(n)=O(\log n ) \end{aligned} W(n)=O(logn)
算法只需要常数规模的存储空间,因此空间复杂度是
S ( n ) = O ( 1 ) \begin{aligned} S(n)=O(1 ) \end{aligned} S(n)=O(1)

3.4

输入三个正整数 a , p , k a, p, k a,p,k, 求 a p   m o d   k a^p\ mod\ k ap mod k 的值. 提示: 由于数据的规模很大, 如果直接计算, 不仅需要采用高精度, 而且时间复杂度很大。例如 1 0 25   m o d   7 = 3 10^{25}\ mod\ 7 = 3 1025 mod 7=3, 但 1 0 25 10^{25} 1025 超出了整型数的表示范围,不能直接计算. 请使用分治策略实现取余运算的算法并给出复杂度分析.

算法设计:根据取余运算的相关性质:
a p a q   m o d   k = ( a p   m o d   k ) ( a q   m o d   k ) a^pa^q\ mod \ k=(a^p\ mod\ k)(a^q\ mod\ k) apaq mod k=(ap mod k)(aq mod k)
由此想到可以对指数运算的取余操作运用分治策略,具体操作可以用以下公式概括:
a p   m o d   k = a p / 2 a p / 2   m o d   k = ( a p / 2   m o d   k ) ( a p / 2   m o d   k ) a^p\ mod\ k=a^{p/2}a^{p/2}\ mod \ k=(a^{p/2}\ mod\ k)(a^{p/2}\ mod\ k) ap mod k=ap/2ap/2 mod k=(ap/2 mod k)(ap/2 mod k)
值得注意的是,在分治过程中 p / 2 p/2 p/2不一定是整数,因此需要额外考虑和处理 p p p为奇数的情况。

数据输入:三个正整数 a , p , k a, p, k a,p,k

结果输出:取余运算结果 r e s u l t result result

伪码描述:

M o d   ( a , p , k ) : Mod\ (a, p, k): Mod (a,p,k):

  1. i f    p = 0 / / 递归终止条件 if\ \ p=0\quad //递归终止条件 if  p=0//递归终止条件
  2. t h e n    r e t u r n    1 then\ \ return\ \ 1 then  return  1
  3. t ← M o d   ( a , p / 2 , k ) / / 递归分治,规模减半 t \leftarrow Mod\ (a, p/2, k) \quad / / 递归分治,规模减半 tMod (a,p/2,k)//递归分治,规模减半
  4. i f    p % 2 = 1 / / 判断 p 是否为奇数 if\ \ p\%2=1\quad //判断p是否为奇数 if  p%2=1//判断p是否为奇数
  5. t h e n   r e t u r n   ( t ∗ t ∗ b ) % k / / 处理 p 为奇数的情况 then \ return \ (t*t*b)\%k\quad//处理p为奇数的情况 then return (ttb)%k//处理p为奇数的情况
  6. e l s e    r e t u r n   ( t ∗ t ) % k / / p 为偶数,正常返回 else\ \ return \ (t*t)\%k\quad//p为偶数,正常返回 else  return (tt)%k//p为偶数,正常返回

递推方程:
{ W ( n ) = W ( n 2 ) + 1 W ( 1 ) = 1 \left\{\begin{array}{l} W(n)=W\left(\frac{n}{2}\right)+1 \\ W(1)=1 \end{array}\right. {W(n)=W(2n)+1W(1)=1
复杂度分析:该算法使用递归分治的思想,每次递归问题的规模减半,因此易得算法的时间复杂度是
W ( n ) = O ( log ⁡ n ) \begin{aligned} W(n)=O(\log n ) \end{aligned} W(n)=O(logn)
算法只需要常数规模的存储空间,因此空间复杂度是
S ( n ) = O ( 1 ) \begin{aligned} S(n)=O(1 ) \end{aligned} S(n)=O(1)

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

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

相关文章

力扣sql入门篇(八)

力扣sql入门篇(八) 1 订单最多的客户 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 SELECT customer_number FROM Orders GROUP BY customer_number having count(order_number)(SELECT max(o1.number)FROM (SELECT count(order_number) numberFRO…

电压放大器在超声导波声弹特性的液压管路压力检测中的应用

实验名称&#xff1a;电压放大器在超声导波声弹特性的液压管路压力检测中的应用 研究方向&#xff1a;超声检测 实验目的&#xff1a; 为实现农机装备液压系统的非介入式压力检测&#xff0c;在分析适合压力检测的超声导波声弹敏感模态与激励频率的基础上&#xff0c;搭建了一套…

用埃式筛法来求解素数。————C++

目录埃式筛法埃式筛法求解某一个数字包含的所有素数数组Code运行结果埃式筛法判断某一个数字是否为素数Code运行结果埃式筛法 首先要了解什么式埃式筛法之前&#xff0c;需要知道一个定理。 就是素数的整数倍一定不是素数。 了解了这个就基本大概懂了埃式筛法。 首先初始化…

C语言线性表实现:顺序表

文章目录&#xff1a;概念理解&#xff1a;1. 动态顺序表结构体&#xff1a;2. 顺序表动态初始化&#xff1a;3. 顺序表扩容&#xff1a;4. 插入&#xff1a;5. 删除&#xff1a;6. 按位序查找&#xff1a;7. 按值查找&#xff1a;8. 输出顺序表&#xff1a;9. 判断顺序表是否相…

UniSCA漏洞优先级排序

当谈到开源漏洞时&#xff0c;我们会发现它们似乎永远处于增长状态。事实上&#xff0c;UniSCA的开源风险报告显示&#xff0c;与2021年同期相比&#xff0c;2022年前9个月添加到UniSCA漏洞数据库中的开源软件漏洞数量增长了33% 。然而&#xff0c;虽然有些漏洞会带来严重的业务…

Altium Designer 20 凡亿教育视频学习-04

第四部分学习 unknow pin错误原因 将原理图导入到PCB时会出现问题 管脚未使用报错 导入PCB器件全部绿 删掉下面的紫红色框架即可&#xff08;Sheet2&#xff09; 视频讲的方法是&#xff1a;一开始把所有的规则删掉&#xff0c;只保留电气规则 板子大小评估-把器件聚集在一…

16---实现权限菜单管理(一)

1、实现角色管理 建role表 USE management; DROP TABLE IF EXISTS role;CREATE TABLE role (id int(11) NOT NULL AUTO_INCREMENT COMMENT id,name varchar(50) DEFAULT NULL COMMENT 名称,description varchar(255) DEFAULT NULL COMMENT 描述,PRIMARY KEY (id) ) ENGINEInn…

活动星投票最美空姐网络评选微信的投票方式线上免费投票

如何进行“最美空姐”的投票活动_投票小程序投票_投票助力方式大家在选择投票小程序之前&#xff0c;可以先梳理一下自己的投票评选活动是哪种类型&#xff0c;目前有匿名投票、图文投票、视频投票、赛事征集投票等。我们现在要以“最美空姐”为主题进行一次投票活动&#xff0…

Docker 三剑客

Docker 三剑客包括Docker Machine、Docker Compose、Docker Swarm。 1. Docker Machine 1.1 简介 Docker Machine 是 Docker 官方三剑客项目之一&#xff0c;使用它可以在多个平台上快速安装部署Docker环境&#xff0c;还可以在短时间内快速构建起一套Docker主机集群。 Do…

最近手头有点紧,于是用Python来冲一波股票...

文章目录前言准备工作获取数据部分爬虫的基本流程代码展示数据可视化分析最后前言 快过年了&#xff0c;手头有点紧&#xff0c;但是作为一个男人&#xff0c;身上怎么能够没有大把钞票呢&#xff1f; 于是我决定用Python来分析一波股票&#xff0c;赢了会所嫩*&#xff0c;输…

在线设计邀请函

不用ps就能制作邀请函的工具&#xff01;在线就能搞定你的邀请函设计和链接分享&#xff01;只要跟着小编下面的设计步骤&#xff0c;掌握在线工具乔拓云轻松设计在线邀请函&#xff0c;在线一键就能生成活动邀请函和邀请函链接&#xff0c;下面就跟着小编的教学开始学习如何在…

【力扣经典题目】复制带随机指针的链表,穿插链表法

题目描述&#xff1a; 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成&#xff0c;其中每个新节点的值都设为其对应的…

接口的理解

文章目录一、接口匿名实现类、匿名对象练习1练习2JDK8接口的新特性一、接口 1、接口使用interface定义 2、Java中接口和类是并列结构 3、如何定义接口——定义接口中的成员 JDK7之前&#xff1a;只能定义全局常量和抽象方法 全局常量&#xff1a;public static final的&#x…

力扣 2042. 检查句子中的数字是否递增

题目 句子是由若干 token 组成的一个列表&#xff0c;token 间用 单个 空格分隔&#xff0c;句子没有前导或尾随空格。每个 token 要么是一个由数字 0-9 组成的不含前导零的 正整数 &#xff0c;要么是一个由小写英文字母组成的 单词 。 示例&#xff0c;“a puppy has 2 eye…

【MySQL】-【索引】

目录为什么使用索引InnoDB中索引的推演索引前的查找设计索引简单的索引设计方案InnoDB中的索引方案为什么使用索引 一、hashmap底层使用红黑树 二、索引时在存储引擎中实现的&#xff0c;因此不同存储引擎的索引可能不同 索引的优点&#xff1a; 类似大学图书馆建书目索引&am…

zookeeper看这一篇就够了

第一章 zookeeper简介 第1节 zookeeper的由来 1 2 3 41. zookeeper最早起源于雅虎研究院的一个研究小组 2. 在雅虎内部很多大型系统基本都需要依赖一个类似的系统来进行分布式协调,并且这个系统还有单点问题 3. 雅虎的开发人员就试图开发一个通用的无单点问题的分布式协调框架…

GIS应用技巧之矢量数据编辑

挺多时候&#xff0c;需要对矢量数据进行编辑&#xff0c;那么如何编辑&#xff1f; 在ArcGIS中修改数据&#xff0c;首先要开始编辑&#xff0c;启动编辑工具条&#xff08;Editor&#xff09;。 目前编辑器处于灰色状态说明没有启动&#xff0c;那么还有些小伙伴可能在GIS主…

【项目实战】传智健康

&#x1f31f;个人博客&#xff1a;www.hellocode.top&#x1f31f; &#x1f31f;Java知识导航&#xff1a;Java-Navigate&#x1f31f; ⭐想获得更好的阅读体验请前往Java-Navigate &#x1f525;本文专栏&#xff1a;《流行框架》 &#x1f31e;如没有JavaWEB基础&#xff0…

Wireshark抓Telnet包及报文分析

Wireshark抓Telnet包及报文分析 Telnet作为应用层第二大协议&#xff0c;用途很多滴。 Telnet到底是个啥子 TELNET协议一种简单的基于文本的协议&#xff0c;它可以用来实现远程终端&#xff0c;让用户可以远程对服务器进行操作。尽管现在的远程终端基本上是基于 ssh 的了&am…

GO语言定时任务实战-gocron包

文章目录1. 基本使用1.1 初始化实例 new()1.2 添加定时任务 AddFunc()1.3 开始定时任务 Start()1.4 完整示例1.5 第一次执行定时任务的契机1.6 spec 的设置2. 粒度到秒2.1 语法示例2.2 完整示例3. 按时间间隔3.1 语法3.2 完整示例&#xff08;every&#xff09;3.3 完整示例引用…