算法之路(二)呈现O(logN)型的三个算法
典型时间复杂度
我们知道算法的执行效率,可以从它的时间复杂度来推算出一二。而典型的时间复杂度有哪些类型呢?
由上图,可以看出,除了常数时间复杂度外,logN型的算法效率是最高的。今天就介绍三种非常easy的logN型算法。
对分查找
给定一个整数X和整数A0,A1,…,An-1,后者已经预先排序并在内存中,求是的Ai= X的下表i,如果X不在数据中,则返回i = -1.
- (int)BinarySearch:(NSArray *)originArray element:(int)element
{
int low, mid, high;
low = 0; high = (int)originArray.count - 1;
while (low <= high) {
mid = (low + high) / 2;
if ([originArray[mid] intValue] < element) {
low = mid + 1;
} else if ([originArray[mid] intValue] > element) {
high = mid -1;
} else {
return mid;
}
}
return -1;
}
* 分析 :*通过上面的程序可以看出,要算出时间复杂度,就是求出while循环的次数。
mid 每次的取值分别是数组长度(N-1)/2,(N-1)/2/2,(N-1)/2/2/2,…,1,0,-1。那么只用求出2的多少次方等于N-1,再加上可能的多需要的次数2。假设2的f次方等于N-1,最大时间即为log(N-1) + 2。因此对分查找的时间复杂度为logN。再举一个实际的例子,假设最初high = 128,low = 0,则mid的最大取值为64,32,16,8,4,2,1,0,-1。大家可以计算时间。
欧几里得算法
第二个是计算最大公因数的欧几里得算法。两个整数的最大公因数Gcd是同时整除二者的最大整数。于是,Gcd(50,15) = 5。
- (unsigned int)Gcd:(unsigned int)m n:(unsigned int)n
{
unsigned int Rem;
while (n > 0) {
Rem = m % n;
m = n;
n = Rem;
}
return m;
}
算法超级简单,但是里面还是有一些精髓的。算法假设m>=n,但是如果m < n,则在第一次while循环后,m和n 会互相交换。
该算法的整个运行时间依赖于确定余数序列的长度,也就是while循环的次数。
依然举例m = 1989 和n = 1590,则余数序列是399,393,6,3,0。从而,Gcd(1989,1590) = 3。
虽然看不出余数的值是按照常数引子递减,有时候递减的非常少,例如从399递减到393。但是,我们可以证明,两次迭代以后,余数最多是原始值的一半。迭代次数至多是2logN,所以时间复杂度是logN。
怎么证明 M > N,则M mod N < M /2呢?
如果N =< M/2,则由于余数小于N,即M mod N < N <= M/2,所以余数也小于M/2。
如果N> M/2,则此时M中有个N,从而余数M-N < M/2。
幂运算
最后一个算法,是计算一个整数的幂。我们可以用乘法的次数作为运行时间的度量。
计算X的N次方常见的算法是使用N-1次乘法自乘。但是用递归算法更好。
- (long)Pow:(long)x n:(unsigned int)n
{
if (n == 0) {
return 1;
}
if (n == 1) {
return x;
}
if ([self isEven:n]) {
return [self Pow:x * x n:n / 2];
} else {
return [self Pow:x * x n:n / 2] * x;
}
}
- (BOOL)isEven:(unsigned int)n
{
if (n % 2 == 0) {
return YES;
} else {
return NO;
}
}
如果N是偶数,则X的N次方 = X的N/2次方乘以X的N/2次方,如果N是奇数,则X的N次方 = X 的(N-1)/2 次方乘以 X的(N-1)/2次方乘以X。
显然,所需要的乘法次数最多是2logN。那么时间复杂度就是logN咯。
算法之路(二)呈现O(logN)型的三个算法的更多相关文章
- 常见算法:C语言求最小公倍数和最大公约数三种算法
最小公倍数:数论中的一种概念,两个整数公有的倍数成为他们的公倍数,当中一个最小的公倍数是他们的最小公倍数,相同地,若干个整数公有的倍数中最小的正整数称为它们的最小公倍数,维基百科:定义点击打开链接 求 ...
- 机器学习(二)——K-均值聚类(K-means)算法
最近在看<机器学习实战>这本书,因为自己本身很想深入的了解机器学习算法,加之想学python,就在朋友的推荐之下选择了这本书进行学习,在写这篇文章之前对FCM有过一定的了解,所以对K均值算 ...
- [4] 算法之路 - 插入排序之Shell间隔与Sedgewick间隔
题目 插入排序法由未排序的后半部前端取出一个值.插入已排序前半部的适当位置.概念简单但速度不快. 排序要加快的基本原则之中的一个: 是让后一次的排序进行时,尽量利用前一次排序后的结果,以加快排序的速度 ...
- 浅谈压缩感知(二十八):压缩感知重构算法之广义正交匹配追踪(gOMP)
主要内容: gOMP的算法流程 gOMP的MATLAB实现 一维信号的实验与结果 稀疏度K与重构成功概率关系的实验与结果 一.gOMP的算法流程 广义正交匹配追踪(Generalized OMP, g ...
- 浅谈压缩感知(二十六):压缩感知重构算法之分段弱正交匹配追踪(SWOMP)
主要内容: SWOMP的算法流程 SWOMP的MATLAB实现 一维信号的实验与结果 门限参数a.测量数M与重构成功概率关系的实验与结果 SWOMP与StOMP性能比较 一.SWOMP的算法流程 分段 ...
- 浅谈压缩感知(二十五):压缩感知重构算法之分段正交匹配追踪(StOMP)
主要内容: StOMP的算法流程 StOMP的MATLAB实现 一维信号的实验与结果 门限参数Ts.测量数M与重构成功概率关系的实验与结果 一.StOMP的算法流程 分段正交匹配追踪(Stagewis ...
- 排序算法总结(二)归并排序【Merge Sort】
一.归并排序原理(Wikipedia) 归并排序本质是分治思想的应用,并且各层分治递归可以同时进行 1.申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列 2.设定两个指针,最初位置 ...
- 我的VSTO之路(二):VSTO程序基本知识
原文:我的VSTO之路(二):VSTO程序基本知识 开始之前,首先我介绍一下我的开发环境:VS2010 + Office 2010,是基于.Net framework 4.0和VSTO 4.0.以下的 ...
- js算法集合(二) javascript实现斐波那契数列 (兔子数列)
js算法集合(二) 斐波那契数列 ★ 上一次我跟大家分享一下做水仙花数的算法的思路,并对其扩展到自幂数的算法,这次,我们来对斐波那契数列进行研究,来加深对循环的理解. Javascript实 ...
随机推荐
- VK Cup 2017 - Round 2
FallDream打的AB都FFT了,只剩一个我打的C,没进前一百,之后看看马拉松复活赛有没机会呗. A. Voltage Keepsake 题目大意:n个东西,每个东西一开始有bi能源,每秒消耗ai ...
- [BZOJ]1027 合金(JSOI2007)
不知道该如何评价吧,很神的一道题,就算是10年前的题目也不可小觑啊. Description 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁 ...
- poj2947 高斯消元
Widget Factory Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 5218 Accepted: 1802 De ...
- 5分钟快速打造WebRTC视频聊天
百度一下WebRTC,我想也是一堆.本以为用这位朋友( 搭建WebRtc环境 )的SkyRTC-demo 就可以一马平川的实现聊天,结果折腾了半天,文本信息都发不出去,更别说视频了.于是自己动手. 想 ...
- What's New In MySQL 8.0
由于8.0内有很多C++11特性.需要gcc4.8版本以上.Rhel6系列默认gcc是4.7.在安装gcc6.1之后仍然检查不过. 原因可能是6.1版本不一定高于4.7,暂不讨论.鉴于升级gc ...
- Java编写高质量代码改善程序的151个建议
第一章 Java开发中通用的方法和准则 建议1:不要在常量和变量中出现易混淆的字母: (i.l.1:o.0等). 建议2:莫让常量蜕变成变量: (代码运行工程中不要改变常量值). 建议3:三元操作符 ...
- Spring Boot Cache Redis缓存
1.集成MyBatis 1.1.引入maven依赖 1.2.生成Mapper 具体可以看MyBatis Generator官网 http://www.mybatis.org/generator/run ...
- Python中的转义
在Python交互式解释器中,输出的字符串会用引号引起来,特殊字符会用反斜杠(\)转义.如果遇到带有\的字符被当作特殊字符时,有以下两种处理方法:1.使用双反斜杠(\\)来转义2.使用原始字符串,方法 ...
- 【java集合系列】---HashSet
在前面的博文中,小编主要简单介绍了java集合中的总体框架,以及list接口中典型的集合ArrayList和LinkedList,接着,我们来看set的部分集合,set集合和数学意义上的集合没有差别, ...
- Dynamics 365 你所期待的子网格编辑终于来了
Dynamics 365的online版本已经在11月1号发布了,on-premises版也在没几天后发布,今天略看了一眼 what's new 一眼就看到了 editable grids,这个不用我 ...