算法练习:最大下标距离

来源:互联网 发布:魔法王座神翼升阶数据 编辑:程序博客网 时间:2024/06/04 18:54

一、题目描述

给定一个整型数组,找出最大下标距离j-i,当且仅当a[j]>a[i]i < j

 

二、直观方案( 时间复杂度为O(n^2) 

对每个元素,从其后找出比其大的元素,并计算下标距离,取距离中的最大值即可。该

方案的时间复杂度为O(n^2)。那么能不能优化下呢?

 

三、优化方案( 时间复杂度为O(n) 

存在这样一个事实,当a[i+1]大于a[i]时,如果在它们的后面存在一个大于它们的元素a[k]k > i+1>i 那么我们就不需要考虑a[i+1],因为明显的k-i > k-(i+1)。举个例子,数组{34, 1, 27 },因为3>4,所以元素73的下标距离大于74的。

基于以上的事实,我们只要从数组的第一个元素开始,找一个下降的序列,从尾部开始扫描,求出最大下标距离。

例如,数组{5, 3, 4, 0, 1, 4, 1},首先找到下降序列{5, 3, 0 },然后依据以下步骤找出答案:

第一步,i = 3j = 6a[3] = 0 < a[6] = 1nMaxSubDistance = 3

第二步,i = 1j = 6a[1] = 3 > a[6] = 1

第三步,i = 1j = 5a[1] = 3 < a[5] = 4nMaxSubDistance = 3

第四步,i = 0j = 5a[0] = 5 > a[5] = 4

第五步,i = 0j = 4a[0] = 5 > a[4] = 1

第六步,i = 0j = 3a[0] = 5 > a[3] = 0

第七步,i = 0j = 2a[0] = 5 > a[2] = 4

第八步,i = 0j = 1a[0] = 5 > a[1] = 3

第九步,i = -1,结束;

 

注意,每次找到一个最大值后,j不需要重置,继续从原来j的位置扫描下去,如果每次j都重置,那算法复杂度就回到O(n^2)了。

 

代码实现如下:

//返回数组中最大下标距离j-i,当且仅当nArray[i]<nArray[j],j>iint MaxSubDistance( int nArray[], int nCount ){//查找一个下降序列bool* bDescSeq = new bool[nCount];memset( bDescSeq, 0, sizeof(bool)*nCount );int nMinNum = nArray[0];for ( int i = 1; i < nCount; ++i ){if ( nArray[i] < nMinNum ){bDescSeq[i] = true;nMinNum = nArray[i];}}int nMaxSubDistance = 0;int i = nCount - 1;int j = nCount - 1;while( i >= 0 ){if( !bDescSeq[i] ){--i;continue;}while( j > i && nArray[i] >= nArray[j] )--j;if ( (j - i) > nMaxSubDistance ){nMaxSubDistance = j - i;//j = nCount - 1;//这句多余,这句加上的话,时间复杂度则为O(n^2)了。}--i;}if ( NULL != bDescSeq ){delete[] bDescSeq;bDescSeq = NULL;}return nMaxSubDistance;}


 

系列文章说明:
1.本系列文章[算法练习],仅仅是本人学习过程的一个记录以及自我激励,没有什么说教的意思。如果能给读者带来些许知识及感悟,那是我的荣幸。
2.本系列文章是本人学习陈东锋老师《进军硅谷,程序员面试揭秘》一书而写的一些心得体会,文章大多数观点均来自此书,特此说明!
3.文章之中,难免有诸多的错误与不足,欢迎读者批评指正,谢谢.


作者:山丘儿
转载请标明出处,谢谢。原文地址:http://blog.csdn.net/s634772208/article/details/46462775

 

 

2 0
原创粉丝点击