您的位置:首页 > 其它

线性查找-数组最大距离

2014-01-02 10:11 260 查看
已知整型数组A
, 问找到最大的 j-i, 符合A[i] < A[j].

方法一:n个数据,两个变量,由于当i,j确定时,每次的比较很简单(A[i] ? A[j]),时间为O(1),所以最原始的暴力解法就是时间O(n^2)。

方法二:我们试着逐步降低时间复杂度。对于符合条件 A[i] < A[j]的 i 和 j,j-i 的可能取值范围为[1,n)。 由于必然存在一个极大值k = j-i, 当j-i > k时, 没有 j-i 符合条件;当j-i < k时,必有 j-i 符合条件(比如k序列的子序列)。所以k是在一个线性分布上的极大值,符合二分查找的应用条件。总的时间复杂度为O(n*lgn)

bool distanceExist(int *A, int n, int k, int& begin){ //k=j-i
for(int i=0;i+k<n;++i){
if(A[i] < A[i+k]){
begin = i;
return true;
}
}
return false;
}
int maxDistance(int *A, int n, int& begin){
int u=n, v=0, m=0;
while(v<u){
m = (u+v)/2;
if(distanceExist(A, n, m, begin)){
v = m+1; //enlarge v to try greater m
}else{ //reduce u to try smaller m
u = m;
}
}
return m;
}
方法三:我们来尝试一下是否存在时间O(n)的解法。考虑到题目中每一个元素A[i]和它右边的元素比较,如果强化一下,让A[i]和它右边所有元素中最大值比较,会有什么效果?



图一,A[] = {3,1,2,3,1,2,1}

如上图所示,我们有原始数组A[] = {3,1,2,3,1,2,1}, 纵坐标Rmax[i]表示的是从A[i]到最右边剩余数组中的最大值。如果我们从左边i=0开始,每次比较A[i] 和 Rmax[j] (i<j), 当A[i] < Rmax[j], 向右移动j, 当A[i] < Rmax[j] 刚刚不成立时,j-1-i即是A[0]到A[j]之间符合条件的最大j-i。因为如果有x<i, 能够符合A[x] < A[j], 由于x在i左边,所以A[x]肯定能够率先扫描到Rmax[j].
然后,同时分别向左移动一位i和j,继续以上过程。因为我们已经确认存在j-1-i了,所以之后只需要考察j-i即可。



图二,A[] = {1,0,0,0,2,1,1}

由于j首先到达右边边界,所以总的时间为O(n)。终于找到了线性查找的方法!一份实现代码如下:

int maxDistance_02(int *A, int n, int& left){
if(n<2) return 0;
int *Rmax = new int
();
Rmax[n-1] = A[n-1];
for(int i=n-2;i>=0;i--){
Rmax[i] = max(A[i], Rmax[i+1]);
}

int l=0, r=0, maxDiff=-1;
while(l<n && r<n){
if(A[l] < Rmax[r]){
if(r-l > maxDiff){
maxDiff = r-l;
left = l;
}
++r;
}else{
++l;
++r; //resume to scan from the potential distance remaining r-l
}
}
delete[] Rmax;
return maxDiff;
}


小结:

1。二分查找的适用情况:待比较值m呈线性分布,并且存在一个极值(极大或极小)作为目标值。

2。对于存在两个变量的情况,如果希望实现时间为线性的查找,那么第一,看是否能够简化两个变量的关系,避免两变量相互独立;第二,当得到两变量某组合时,对数据的处理能否简化到时间O(1)。

注:题目来自leetcode, 同时也附有解法。不过网站在介绍O(n*lgn)的解法时用了排序,相比于我这里原创的方法二,既多用了空间,又多了一遍扫描,所以没有引用。网站介绍的O(n)的解法("Best Solution"),过于晦涩也没有完整代码,我从评论中找到一份实现,作为这里的方法三。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐