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

注:本题解可能不唯一。如何查找所有解?

算法:设数组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[n];		// 回溯使用
	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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值