有趣的算法(十一) ——分治法:快速求最值
有趣的算法(十一)——分治法:快速求最值
(原创内容,转载请注明来源,谢谢)
一、需求
一个数组,里面有若干的数字,现需要得到这一组数字的最大值和最小值。
二、简单分析
最基本的做法,是两两比对,可以区分出临时的最大值和最小值,再拿临时的最大值和最小值往后比较,有新的最值则更新。总的需要的比较次数是2n-2。
三、优化
使用分治法快速求最值。即把数组分到最小的1-2个数,两两比较后,仅将最大值和最小值回传,再两两比较最值,回传新的最值,最终得出最大值和最小值。
分析需要比较的次数。当数组只有1个数时,T(1)=0;2个数时,T(2)=1。n个数字时,T(n)=2T(n/2)+2。
推导T(n)=2T(n/2)+2= 22T(n/22)+22+2…=2k-1T(2)+2k-1+2k-2+…22+2=2k-1+2k-2。
因此,当n=2k时,需要的次数是n/2+n-2=3n/2-2。当n不是2k,则次数会比3n/2-2略多,正好2的k次的数组长度时,这种算法较快。
四、实现
使用php编程,代码如下:
<?php
$x = 0;
//快速求最值-返回 array(min, max)
function quickMost(array $nums)
{
$len = count($nums);
if(1 == $len)
{
returnarray(reset($nums), reset($nums));
}
if(2 == $len)
{
$min =reset($nums);
$max =next($nums);
if($min >$max)
{
$tmp= $min;
$min= $max;
$max= $tmp;
}
$GLOBALS['x']++;
returnarray($min, $max);
}
$arr1 =array_slice($nums, floor($len/2));
$arr2 =array_diff($nums, $arr1);
list($min1, $max1) =quickMost($arr1);
list($min2, $max2) =quickMost($arr2);
$min = $min1 <=$min2 ? $min1 : $min2;
$GLOBALS['x']++;
$max = $max1 >=$max2 ? $max1 : $max2;
$GLOBALS['x']++;
return array($min,$max);
}
$testArr = array(7,8,5,1,4,9,0,3);
$res = quickMost($testArr);
var_dump($res);
echo $x;
结果如下:
aarray(2) { [0]=> int(1) [1]=> int(9) }
10
正确算出了最值,数字个数为8,则预测的比较次数为3n/2-2=3*8/2-2=10,和输出结果一致。
说明:
这里用到里一个php的array_diff,返回的是一个数组有的且另一个数组没有的数字,这样一定程度上如果有重复数字可以减少比较的次数。
但是,存在问题,当diff后,由于是返回一个差集,因此第二个数组可能是空树组的情况,例如输入的需要比较的数组为(1,1,1,1,1,1),此时的$arr2会是空树组,则会报错。因此,需要在第二次递归调用quickMost方法时,进行一个判断,即可正确解决此问题。修改如下:
if(false == empty($arr2))
{
list($min2, $max2) =quickMost($arr2);
$min = $min <= $min2 ?$min : $min2;
$GLOBALS['x']++;
$max = $max >= $max2 ?$max : $max2;
$GLOBALS['x']++;
}
——written by linhxx 2018.01.18
- npm5 新版功能特性解析及与 yarn 评测对比
- H5直播避坑指南
- 龙门阵之 DevOps 门外汉须知
- 全面进阶 H5 直播(上)
- 这年头,不会斗图都毕不了业?
- 龙妈也会死?《权力的游戏》 AI 算法预测丹妮女王危在旦夕
- 腾讯云 GAME-TECH 沙龙干货回顾:海外网络拓展及质量把控
- 通过扩展让ASP.NET Web API支持W3C的CORS规范
- 腾讯云GAME-TECH沙龙干货回顾:腾讯游戏云全球化实践
- 腾讯云GAME-TECH沙龙干货回顾:猎豹游戏出海经验分享
- 腾讯云GAME-TECH沙龙干货回顾:绿洲全球化案例分享
- 基于云计算的 CV 移动交互应用研究(1):CV交互+云计算
- ARKit 进阶:物理世界
- HLS 视频点播初探
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 队列的一种实现:循环队列
- StackExchange.Redis .net core Timeout performing 超时问题
- G1 垃圾回收器简单调优
- Docker安装官方Redis镜像并启用密码认证 实践笔记
- Asp.net Core 使用Jenkins + Dockor 实现持续集成、自动化部署(四):发布与回滚
- linux centos 安装Jenkins(非docker方式)
- mysql5.7 derived_merge=on 弄丢了我的 order by!
- 用nrm轻松管理npm镜像 自用 实践笔记
- 模拟战役(DFS||并查集解法)
- 学会这些(滑动关机、应用多开、QQ微信消息攻击、表白神器),逼格瞬间提升1000倍
- 位数问题
- 题目 2229: [蓝桥杯][算法训练]最大最小公倍数
- 武汉工程大学2020GPLT选拔赛(重现赛)详细代码讲解
- 用邻接链表存图 详讲
- strstr函数的详细讲解