《剑指offer》:[38]数字在排序数组中出现的次数

    “沟通、学习能力就是看面试者能否清晰、有条理地表达自己,是否会在自己所得到的信息不够的情况下主动发问澄清,能否在得到一些暗示之后迅速做出反应纠正错误”                                                                                                                   ---陈黎明(MSoft-SDE)
题目:统计一个数字在排序数组中出现的次数。例如输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3在数组中出现的次数是4,所以输出4。
方案一:顺序扫描,找到一个计数器+1。这个不用多介绍,时间复杂为O(N),空间复杂度为O(1)。
方案二:此方案相比于方案一,效率稍有提高,但是其实也差不多。就是采用二分查找,先找到给出的数字3,然后再向前以及向后顺序查找它的开头和结尾。由于查找该数字的时间复杂度为O(logN),但是顺序查找该数字的开始和结尾(如果对于N个数字,该数字出现了N次)的时间复杂度都为O(N),所以该算法的时间复杂度仍然为O(N)。只有针对有N个元素,但是该元素出现的次数很少的情况下,此算法相比于算法二才有相对的提高。
方案三:次算法是相比于方案2的提高改进。针对如果要统计的数字出现的次数和数字N的个数相同的情况下,其时间复杂度为O(N),如果我们在找到该数字后,在找其头和尾的时候也采用二分查找呢?那么此时的情况就不一样了!由于查找该数字,以及查找该数字的开始和结尾的时间复杂度都为O(logN),所以此时该算法的时间复杂度为O(logN)。
方案三的具体实现代码如下:
#include <iostream>
using namespace std;
int arr[8]={1,2,3,3,3,3,4,5};
int GetFirstK(int *array,int k,int length,int start ,int end)
{
	if(start>end)
		return -1;
	int middleIndex=(start+end)/2;
	int middledata=array[middleIndex];
	if(middledata==k)
	{
		if(middleIndex>0 && array[middleIndex-1]!=k || middleIndex==0)
			return middleIndex;
		else
			end=middleIndex-1;
	}
	else if(middledata>k)
		end=middleIndex-1;
	else
		start=middleIndex+1;
	return GetFirstK(array,k,length,start,end);
}


int GetLastK(int *array,int k,int length,int start,int end)
{
	if(start>end)
		return -1;
	int middleIndex=(start+end)/2;
	int middledata=array[middleIndex];
	if(middledata==k)
	{
		if(middleIndex<length-1 && array[middleIndex+1]!=k || middleIndex==length-1)
			return middleIndex;
		else
			start=middleIndex+1;
	}
	else if(middledata>k)
		end=middleIndex-1;
	else
		start=middleIndex+1;
	return GetLastK(array,k,length,start,end);
}
int GetNumK(int *array,int length,int k)
{
	int number=0;
	if(array!=NULL && length>0)
	{
		int first=GetFirstK(array,k,length,0,length-1);
		int last=GetLastK(array,k,length,0,length-1);
		if(first>-1 && last>-1)
			number=last-first+1;
		else
			return 0;
	}
	return number;
}
int main()
{
	int num=GetNumK(arr,8,3);
	cout<<"3出现的次数是:"<<num<<endl;
	system("pause");
	return 0;
}

运行结果是:



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值