线性查找-数组最大距离

来源:互联网 发布:美国2016年gdp数据 编辑:程序博客网 时间:2024/04/30 06:55

已知整型数组A[n], 问找到最大的 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[n]();    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"),过于晦涩也没有完整代码,我从评论中找到一份实现,作为这里的方法三。

0 0
原创粉丝点击