求数组中满足以下条件的相距最远的元素(即j - i 的值最大):
1. a[i] < a[j]
2. i < j
题目出处:LeetCode
(按ctrl + A查看提示和代码)
提示:可以在O(N)时间和O(N)空间复杂度内解决。
解法:
首先我们可以用一个长度为N的数组RMax记录从每一个位置i开始往后最大的元素。
从数组末端开始往前遍历,对于每个位置i的元素:
1) 如果它比i+1位置元素小,那么i处的元素max可以被i+1处覆盖。因为a[i] < a[i+1],如果存在a[i]之前的某个元素a[k] < a[i],那么必然也有a[k] < a[i+1],且i + 1 - k > i - k, 于是a[i+1]是一个更好的选择。
2) 如果比i+1位置的元素大,我们将i处的max元素置为a[i],因为虽然a[i]比a[i+1]位置靠前,但其值较大,可能匹配到前面更多的元素。
当遍历完成,我们得到了一个降序的数组RMax。
然后我们开始从头遍历数组分别设置两个指针指向原数组a和辅助数组RMax的头,取数组中的元素a[i],不断和RMax里的元素比较,对于a[i]<RMax[j],我们可以继续用a[i]跟下一个元素RMax[j+1]比较,因为RMax是降序的,当a[i]和RMax的某个元素不匹配时,此时i, j的距离应该就是a[i]能到达的最大距离,后续不可能再有比a[i]大的元素了。此时可以继续用a[i+1]和RMax比较,如果a[i+1] < a[i],则可能匹配到更后面的元素。
如此循环继续。同时用一个maxDist变量记录a[i]失配时i-j的最大值。
C++代码:
int GetMaxDist(int *a, int len){
if(!a || len < 2) return 0;
int *RMax = new int[len];
RMax[len-1] = a[len-1];
for(int i = len-2; i >= 0; --i){
RMax[i] = a[i] > RMax[i +1]?a[i]:RMax[i+1];
}
int maxDist = 0, dist = 0, c = a[0];
for(int i = 1; i < len; ++i){
if(c < RMax[i]){
dist++;
}else{
c = a[i];
if(dist > maxDist) maxDist = dist;
dist = 0;
}
}
if(dist > maxDist) maxDist = dist;
return maxDist;
}