《剑指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;
}

运行结果是:

时间: 2024-10-26 13:53:26

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

剑指offer 面试题38—数字在排序数组中出现的次数

题目: 统计一个数字在排序数组中出现的次数.例如输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4. 解法一:O(n) 顺序遍历 解法二:O(logn) 用二分查找,分别找出第一个3,和最后一个3的位置,然后计算个数. #include <stdio.h> int GetFirstK(int* data,int length,int k,int start,int end) { if(start > end) return -1; int m

【剑指offer】题目38 数字在排序数组中出现的次数

思路: 应该是用二分查找分别找到该数字第一次和最后一次出现的位置,相减即可.O(logn) int findLeft(int a[], int n, int num) { int l = 0, r = n - 1; while(l <= r) { int m = l + (r - l) / 2; if(a[m] == num) //与普通二分查找的区别在等于这里 { if(m == 0 || a[m - 1] != num) //如果这是第一个数字或者它前面的数字不是num那么这个位置就是第一个

38.数字在排序数组中出现的次数

半段查找. int GetFirstK(int* data, int length, int k, int start, int end) { if (start > end) return -1; int middleIndex = (start + end) / 2; int middleData = data[middleIndex]; if (middleData == k) { if ((middleIndex > 0 && data[middleIndex - 1]

剑指offer 38 数字在排序数组中出现的次数

自己的写法 class Solution { public: int GetNumberOfK(vector<int> data ,int k) { int length = data.size(); if(length <= 0) return 0; for(int i = 0;i < length;i++){ } int index1 = GetFirst(data,k,0,length-1); int index2 = GetLast(data,k,0,length-1);

剑指offer——面试题38:数字在排序数组中出现的次数(利用二分查找来找第一次和最后一次的位置)

题目: 统计一个数字在排序数组中出现的次数. 思路: 因为是排好序的数组,所以可以采用二分查找的算法. 一般最容易想到的思路是采用二分查找先找到一个,然后往他左右两边遍历,但是这个方法由于在n个数组中还可能有n个k,所以 查找的复杂度还是O(n) 可以先用二分查找算法找到第一个出现的位置,即当找到一个时,看它前面一个是否也是k或者是否已经是查找这段的第一个了 然后同样用二分查找找最后一个出现的位置. 1 #include<iostream> 2 #include<vector> 3

剑指offer面试题38:数字在排序数组中出现的次数

题目描述: 统计一个数字在排序数组中出现的次数. 输入: 每个测试案例包括两行: 第一行有1个整数n,表示数组的大小.1<=n <= 10^6. 第二行有n个整数,表示数组元素,每个元素均为int. 第三行有1个整数m,表示接下来有m次查询.1<=m<=10^3. 下面有m行,每行有一个整数k,表示要查询的数. 输出: 对应每个测试案例,有m行输出,每行1整数,表示数组中该数字出现的次数. 样例输入: 81 2 3 3 3 3 4 513 样例输出: 4 //source:http

【剑指offer】面试题38:数字在排序数组中出现的次数

题目: 统计一个数字在排序数组中出现的次数. 思路: 对二分查找进行改进,找到数字在数组中第一次出现和最后一次出现的位置,这样就得到它出现的次数. 以找第一次出现的位置为例:如果mid元素大于k,则在前半段找:如果小于k,则在后半段找:如果等于k,则要看mid的前一个元素是不是k,如果是,则在前半段找,如果不是,则这就是第一次出现的位置. 时间复杂度O(logn). 代码: class Solution { public: int GetNumberOfK(vector<int> data ,

(剑指Offer)面试题38:数字在排序数组中出现的次数

题目: 统计一个数字在排序数组中出现的次数. 思路: 1.顺序遍历 顺序扫描一遍数组,统计该数字出现的次数. 时间复杂度:O(n) 2.二分查找 假设我们需要找的数字是k,那么就需要找到数组中的第一个k和最后一个k出现的位置. 如何通过二分查找得到第一个k的位置呢? 取数组中间的数字与k作比较, 如果该数字比k大,那么k只能出现在前半部分,那么下一轮只能在前半部分找: 如果该数字比k小,那么k只能出现在后半部分,那么下一轮只能在后半部分找: 如果该数字等于k,需要判断这是不是第一个k,如果该数字

38 - 数字在排序数组中的次数

题目描述: 统计一个数字在排序数组中出现的次数. 如输入排序数组 {1,2,3,3,3,3,4,5} 和数字3,由于 3 在数组中出现了 4 次,因此输出 4. 解析: 在有序数组中查找一个数可以联想到二分查找. 如例子中,要查找3的次数,二分查找,找到3后,它的左右两边可能都有3,因此两边都要查找,如果3在数组中出现了n次,则时间复杂度O(n),二分查找没有起到作用. 假设我们要在数组中查找 k 的次数.因为数组是有序的,那么只要找到数组中的第一个 k 和最后一个 k 就能够确定出现的次数.