3*n/2 - 2
求区间范围最小值最大值
用分治法(Divide and Conquer)求n元数组最小元与最大元,当n=1时,不用比较,最大元和最小元都是这个数;当n=2时,一次比较就可以找出两个数据元素的最大元和最小元;当n>2时,可以把n个数据元素分为大致相等的两半,一半有n/2个数据元素,而另一半有n/2个数据元素。先分别找出各自组中的最大元和最小元,然后将两个最大元进行比较,就可得n个元素的最大元;将两个最小元进行比较,就可得n个元素的最小元。
在规模为n的数据元素集合中找出最大元和最小元, 至少需要3n/2-2次比较,即3n/2-2是找最大最小元算法的下界。当n=2k,或当n≠2k时,若n是若干2的整数幂之和,则算法的时间复杂度仍可达到下界3n/2-2。
a.为一个分治算法编写伪代码,该算法同时求出一个n元数组的最大元素和最小元素的值。
b.请拿该算法与解同样问题的蛮力算法做一个比较。
解答:
a.同时求出最大值和最小值,只需要将原数组一分为二,再使用相同的方法找出这两个部分中的最大值和最小值,然后经过比较就可以得到整个问题的最大值和最小值。
算法 minmax_element(A[l..r], min, max)
// 该算法利用分治技术得到数组A中的最大值和最小值
// 输入:数值数组A[l..r]
// 输出:最小值min和最大值max
if(r<0) return; // 空数组,没有最大最小元
if(r==0) max=min=A[0]; // 只有一个元素时
if(r==1) {min=A[0]<=A[1]?A[0]:A[1]; max=A[0]<=A[1]?A[1]:A[0];} // 有两元素时
else
{
m=int((l+r)/2); // 去中间值,把数组分成两个部分
minmax_element(l, m, fMin, fMax); // 递归解决前一部分
minmax_element(m+1, r, sMin, sMax); // 递归解决后一部分
max= std::max(fMax, sMax); // 从两部分的两个最大值中选择大值
min= std::min(fMin, sMin); // 从两部分的两个最小值中选择小值
}
为了数据类型一般话,我们采用 C++ 的模板。将最小最大数对存储在 std::pair 类型中。
template<class ForwardIt, class Compare>
std::pair<ForwardIt, ForwardIt> minmax_element(ForwardIt first, ForwardIt last, Compare comp)
{
std::pair<ForwardIt, ForwardIt> result(first, first); if(first == last) return result;
if(++first == last) return result; if(comp(*first, *result.first))
result.first = first;
else
result.second = first; while(++first != last)
{
ForwardIt i = first;
if(++first == last)
{
if(comp(*i, *result.first))
result.first = i;
else if (!(comp(*i, *result.second)))
result.second = i;
break;
}
else
{
if(comp(*first, *i))
{
if(comp(*first, *result.first))
result.first = first;
if(!(comp(*i, *result.second)))
result.second = i;
}
else
{
if(comp(*i, *result.first))
result.first = i;
if(!(comp(*first, *result.second)))
result.second = first;
}
}
}
return result;
}
时间复杂度为:
t(n)=2*t(n/2)+2 n>2
t(1)=0 t(2)=1
设n=2^k,则n/2=2^(k-1)
t(n)=t(2^k)=2*t[2^(k-1)]+2
=2[2*t(2^(k-2))+2]+2
=2^2*t[2^(k-2))]+2^2+2
=2^2[2*t[2^(k-3)]+2]+2^2+2
=2^3*t[2^(k-3)]+2^3+2^2+2
=...
=2^(k-1)*t(2)+2^(k-1)+2^(k-2)+...+2 // t(2)=1
=2^(k-1)+2^(k-1)+2^(k-2)+...+2 // 后面部分为等比数列求和
=2^(k-1)+2^k-2 // 2^(k-1)=n/2, 2^k=n
=n/2+n-2
=3*n/2-2
b.蛮力法的算法如下:
算法 simple_minmax(A[0..n])
// 用蛮力法得到数组A的最大值和最小值
// 输入:数值数组A[l..r]
// 输出:最小值min和最大值max
max=min=A[0];
for(i=0; i<n; ++i)
{
if(A[i]>max) max=A[i];
if(A[i]<min) min=A[i];
}
蛮力算法的时间复杂度t(n)=2*(n-1)
C++ 的头文件 <algorithm>包含了上面两种算法。
3*n/2-2 对应 std::minmax_element
2*(n-1) 对应std::min_element + std::max_element
算法 minmax_element 的时间复杂度为3*n/2-2,simple_minmax 的时间复杂度为2n-2,都属于Θ(n)复杂度。
但比较可得,minmax_element 减少了不必要的比较,速度上比 simple_minmax 的快一些。
随机推荐
- spring batch资料收集
spring batch官网 Spring Batch在大型企业中的最佳实践 一篇文章全面解析大数据批处理框架Spring Batch Spring Batch系列总括
- UP Board 串口使用心得
前言 原创文章,转载引用务必注明链接. 本文使用Markdown写成,为获得更好的阅读体验和正常的图片.链接,请访问我的博客: http://www.cnblogs.com/sjqlwy/p/up_s ...
- 【原创】贴个dirtycow(脏牛漏洞)不死机的exploit
dirtycow官网上几个获得rootshell的exp大都会导致机器死机,在原作者的基础上改进了一下,做个记录: /* * (un)comment correct payload first (x8 ...
- Thinkphp文件上传
1.在IndexController.class.php里面写2个方法,shangchuan用来显示页面,upload是上传文件的方法. <?php namespace Home\Control ...
- [Unreal]学习笔记001
常规 为了便于控制,创建自己的Gamemode和Controller,再通过Setting->World Setting进行设置 在场景中,按住鼠标右键来移动视角,按住右键的同时按下W/S,控制 ...
- Zabbix自定义监控8080端口的连接数
Zabbix自定义监控8080端口的连接数 一 zabbix自定义监控实现思路 实际上我们要想使用zabbix来监控一些服务的原理很简单,步骤分别是:1.写一个脚本用于获取待监控服务的一些状态信息2. ...
- runtime-给系统已有类添加属性
在没有接触runtime之前,我们接触到的能给类进行扩展的方法有类目(category)和延展(extension)两种.类目(category)可以给系统已有类添加扩展方法但是不能添加属性,并且被添 ...
- WCF学习第二篇:WCF 配置架构。这有助于对wcf配置的理解和记忆
使用 Windows Communication Foundation (WCF) 配置元素,您可以配置 WCF 服务和客户端应用程序. 可以使用配置编辑器工具 (SvcConfigEditor.ex ...
- linux下, 再次遇到使用thinkphp的模板标签时,报错used undefined function \Think\Template\simplexml_load_string() 是因为没有安装 php-xml包
linux下, 使用thinkphp的模板标签,如 eq, gt, volist defined, present , empty等 标签时, 报错: used undefined function ...
- c++ 接口和抽象类
其实对抽象类与接口的区别一直是搞不太清楚,最近正在学习<设计模式>,期间用到了很多c++多态的知识.这是才恍然发现,是应该整理下这方面的知识了.但在翻阅书本.上网查阅资料之际,发现有篇文章 ...