算法竞赛入门经典:第八章 高效算法设计 8.6二分查找之lowerBound

/*
深入:
注意:对于二分查找的一个系列,high都是用数组长度来计算,真正是取不到的
如果数组中多个元素都是v,上面的函数返回的是中间的一个。能不能呢个求出值等于v的完整区间呢?
下面的程序当v存在时返回它出现的第一个位置。如果不存在,返回这样一个下标i:在此处插入v(原来的元素A[i],A[i+1],..全部往后移动一个位置)后序列仍然有序

分析:
最后的返回值不仅可能是x,x+1,x+2,...,y-1,(原区间),也可能是y(当v>A[y-1]时)。
查找区间[x,y),返回值区间[x,y]
iArr[mid] < iVal,说明待找元素应该在后半区间,并且mid不可能,因此范围在[mid+1,y]
iArr[mid] = iVal,易错,注意,不是mid,因为前面可能还有与中间值相同的元素,因此mid有可能,范围为[x,mid]
iArr[mid] > iVal,范围为[x,mid]
所以iArr[mid] < iVal,low = mid+1,
    iArr[mid] >= iVal,high = mid
输入:
8
0 1 3 4 6 7 9 9
5

8
0 1 4 4 4 4 9 9
4
输出:
4
2
*/
#include <stdio.h>
#define MAXSIZE 1024

int lowerBound(int* iArr,int low,int high,int iVal)
{
	while(low < high)
	{
		int mid = low + (high - low)/2;
		if(iArr[mid] >= iVal)
		{
			high = mid;
		}
		else
		{
			low = mid + 1;
		}
	}
	return high;
}

void process()
{
	int n;
	while(EOF != scanf("%d",&n))
	{
		int iArr[MAXSIZE];
		for(int i = 0; i < n ; i++)
		{
			scanf("%d",&iArr[i]);
		}
		//sort(iArr,iArr+n);
		int iVal;
		scanf("%d",&iVal);
		printf("%d\n",lowerBound(iArr,0,n,iVal));
	}
}

int main(int argc,char* argv[])
{
	process();
	getchar();
	return 0;
}

你可能感兴趣的:(二分查找)