您的位置:首页 > 其它

在一个int数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数。

2012-04-25 01:05 369 查看
注:本题解可能不唯一。如何查找所有解?

算法:设数组a[0...n-1],设有左右两个游标i,j。左游标右移过程中的最大值为max,右游标左移过程中的最小值为min。则当i==j时且min>=max,则有解,其中一解就是a[i]

算法是这样的:

1)初始化i = 0,j = n-1,max = a[0],min = a[n-1]

2)如果a[i] < max 则i++

3)如果a[j] > min 则j--

4)如果a[i] >= max 且a[j] <= min,则需要使i++或使j--

当a[i+1] <= min时,i++,并更新max;否则如果i++,就会造成左侧数大于右侧数无法求得解

当a[j-1] >= max时,j--,并更新min;否则由于此时的max可能已经被更新,如果j--就会造成右侧数小于左侧数,无法得解

由于当j - i == 1时上面两种情况不可能同时发生,因此避免了两个游标更新后造成j < i的问题,但是可能会出现上面两种情况均不发生的情形,此时说明j-i > 1,且max > min;此时需要对i进行回溯。

此种算法时间复杂度为O(n), 空间复杂度为O(n)。

// 在一个int数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数。
bool FindValue(int data[], int n, int& find)
{
int maxTemp = data[0], minTemp = data[n-1];
int i = 0, j = n-1;
int* temp = new int
;		// 回溯使用
while(i != j)
{
temp[i] = maxTemp;
// 回溯条件
if(maxTemp > minTemp)
{
--i;
if(i < 0)
break;
maxTemp = temp[i];
--j;
minTemp = min(data[j], minTemp);
continue;
}
bool bFlag1 = data[i+1] >= maxTemp;
bool bFlag2 = data[j-1] <= minTemp;
// 优先滑动不符合的当前滑标
if(!bFlag1)
{
++i;
}
if(!bFlag2)
{
--j;
}
// 此处可能需要修正左侧最大值,右侧最小值
if(bFlag1 && bFlag2)
{
bool bL = false;
bool bR = false;
// 只有当左侧游标的下一值满足此条件时才右移游标
if(data[i+1] <= minTemp)
{
++i;
maxTemp = data[i];
bL = true;
}
// 此时可能已经更新了左游标,判断右游标是否需要移动
if(data[j-1] >= maxTemp)
{
--j;
minTemp = data[j];
bR = true;
}
// 如果两个游标都不能移动,需要回溯
if(!bL && !bR)
{
// 回溯
--i;
if(i < 0)
break;
maxTemp = temp[i];
--j;
minTemp = min(data[j], minTemp);
}
}
}
if(i == j)
find = data[i];
delete[] temp;
return (i == j);
}


PS:如果要获得所有满足条件的解,需另设置两个监测站,q1,q2,分别存储i和j最后一次跳变前得位置。所有满足条件的解即为(q1,q2)。不包括q1和q2
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐