【一些题】剑指offer:找出一个数字在排序数组中出现的次数

方法一:从前往后找出第一个出现的target;从后往前找出最后一个出现的target。程序如下

int CountInSorted(int *num, int length, int target);

void main()
{
	clock_t ClockBegin = clock();
	const int L = 8;
	int num[L] = {1,2,3,3,3,3,4,5};
	int result = CountInSorted(num, 8, 3);
	//int result = NumReversePair(num, 5);

	clock_t ClockEnd = clock();
	cout << result << endl;
	cout << ClockEnd-ClockBegin << "ms" <<endl;

	system("pause");
	return;
}

int CountInSorted(int *num, int length, int target)
{
	if(!num || length < 0)
		return -1;
	int begin = 0, end = length-1;
	while(num[begin]!= target && begin < length)  //从前往后扫描
	{	++begin; }
	while(num[end]!=target && end >= begin)  //从后往前扫描
	{	--end; }
	return (end >= begin)?(end - begin +1) : -1;
}

**************************************************

方法二:利用二分法,先找出第一个目标值出现的位置,再由此位置往前,往后搜索第一个和最后一个出现位置。

程序如下:

int FindTarget(int *num, int begin, int end, int target);
int CountInSorted(int *num, int length, int target);


int main()
{
	clock_t clockbegin,clockend;
	
	clockbegin = clock();
	const int L = 8;
	int num[L] = {1,2,3,3,3,3,4,5};
	int result = CountInSorted(num, 8, 3);

	clockend = clock();
	cout << clockend-clockbegin << endl;
	cout << result << "ms" << endl;
	system("pause");
	
 return 0;
}

int FindTarget(int *num, int begin, int end, int target)
{
	if(!num ||(end<begin))
		return -1;
	int mid = begin + ((end-begin)>>1) ;
	if(num[mid] == target)
		return mid;
	else if(num[mid] > target)
		return FindTarget(num, begin, mid-1, target);
	else 
		return FindTarget(num, mid+1, end, target);
}

int CountInSorted(int *num, int length, int target)
{
	if(!num || length <= 0)
		return -1;
	//在排序数组中找到一个目标值的位置
	int index = FindTarget(num, 0, length-1, target); 
	//如果能找到一个位置,则再往前,往后寻找第一个和最后一个target位置;
	//如果没有找到一个位置,说明数组中没有target,返回-1
	if(index<0)
	{	return -1;}
	else
	{
		int backward = index-1, forward = index+1;
		//找到第一个target
		while(num[backward] == target && backward >= 0)
		{	--backward; }
		++backward;
		//找到最后一个target
		while(num[forward] == target && forward < length)
		{	++forward; }
		--forward;

		return (forward - backward + 1);
	}

}

*********************************************************

方法三:将二分搜索进行到底,不仅用二分搜索找到“一个”target位置,而且用二分搜索找到第一个和最后一个target位置。(因为看到方法二中的很多计算花在了向前,向后搜索第一个和最后一个target位置,而既然是在sorted中进行搜索,就尝试用二分搜索代替顺序搜索)。

程序如下

int CountInSorted(int *num, int length, int target);
int FindFirstInSorted(int *num, int begin, int end, int target);
int FindLastInSorted(int *num, int begin, int end, int target);


int main()
{
	clock_t clockbegin,clockend;
	
	clockbegin = clock();
	const int L = 8;
	int num[L] = {1,2,3,3,3,3,4,5};
	int result = CountInSorted(num, 8, 3);

	clockend = clock();
	cout << clockend-clockbegin << endl;
	cout << result << "ms" << endl;
	system("pause");
	
 return 0;
}

int FindFirstInSorted(int *num, int begin, int end, int target)
{
	if(!num || end < begin)
		return -1;
	int mid = begin + ((end-begin)>>1);
	//找到一个target位置后不直接返回,而是看前一个是否也为target
	if(num[mid] == target)
	{
		if(mid -1 >=begin && num[mid-1] == target)
		{	return FindFirstInSorted(num, begin, mid-1, target); }
		else
			return mid;
	}
	else if(num[mid] > target)
		return FindFirstInSorted(num, begin, mid-1, target);
	else
		return FindFirstInSorted(num, mid+1, end, target);
}

int FindLastInSorted(int *num, int begin, int end, int target)
{
	if(!num || end < begin)
		return -1;
	int mid = begin + ((end-begin)>>1);
	//找到一个target位置后不直接返回,而是看前一个是否也为target
	if(num[mid] == target)
	{
		if(mid +1 <=end && num[mid+1] == target)
		{	return FindLastInSorted(num, mid+1, end, target); }
		else
			return mid;
	}
	else if(num[mid] > target)
		return FindLastInSorted(num, begin, mid-1, target);
	else
		return FindLastInSorted(num, mid+1, end, target);
}

int CountInSorted(int *num, int length, int target)
{
	//配合二分查找的CountInSorted
	if(!num || length <= 0)
		return -1;
	int first = FindFirstInSorted(num, 0,length-1, target);
	int last = FindLastInSorted(num, 0,length-1, target);
	return (last-first+1);
}

感受:我去,是不是感觉快了很多呀?应该不会,因为数据量这么小,应该感觉不出什么来的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值