【剑指】53(1).数字在排序数组中出现的次数

本文介绍了一种算法,用于统计一个数字在已排序数组中出现的次数,并提供了C++实现代码及测试案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述
  • 统计一个数字在排序数组中出现的次数。例如输入排序数组{1, 2, 3, 3, 3, 3, 4, 5}和数字3,由于3在这个数组中出现了4次,因此输出4。
算法分析
  • 对有序数组进行折半查找,找出数字第一个出现的位置和最后一个出现的位置,求出出现的次数。

提交代码:

class Solution {
public:
	int GetNumberOfK(vector<int> data, int k) {
		if (data.empty())
			return 0;
		// 折半查找开头
		int beg, last;
		int start = 0;
		int end = data.size() - 1;
		while (start < end)
		{
			int middle = (start + end) / 2;
			if (data[middle] < k)
				start = middle + 1;
			else if(data[middle] > k)
				end = middle - 1;
			// 相等时
			else
			{
				// 前一位相等
				if (middle > 0 && data[middle - 1] == k)
					end = middle - 1;
				// 前一位已经没有了
				else
				{
					start = middle;
					break;
				}
					
			}
		}

		if (data[start] != k)
			return 0;

		beg = start;
		// 折半查找结尾
		start = 0;
		end = data.size() - 1;
		while (start < end)
		{
			int middle = (start + end) / 2;
			if (data[middle] < k)
				start = middle + 1;
			else if (data[middle] > k)
				end = middle - 1;
			// 相等时
			else
			{
				// 后一位相等
				if (middle < (data.size() - 1) &&
					data[middle + 1] == k)
					start = middle + 1;
				// 后一位已经没有了
				else
				{
					end = middle;
					break;
				}
			}
		}
		last = end;

		return (last - beg + 1);
	}
};

测试代码:

// ====================测试代码====================
void Test(const char* testName, vector<int> data, int k, int expected)
{
	if (testName != nullptr)
		printf("%s begins: ", testName);

	Solution s;
	int result = s.GetNumberOfK(data, k);
	if (result == expected)
		printf("Passed.\n");
	else
		printf("Failed.\n");
}

// 查找的数字出现在数组的中间
void Test1()
{
	vector<int> data = { 1, 2, 3, 3, 3, 3, 4, 5 };
	Test("Test1", data, 3, 4);
}

// 查找的数组出现在数组的开头
void Test2()
{
	vector<int> data = { 3, 3, 3, 3, 4, 5 };
	Test("Test2", data, 3, 4);
}

// 查找的数组出现在数组的结尾
void Test3()
{
	vector<int> data = { 1, 2, 3, 3, 3, 3 };
	Test("Test3", data, 3, 4);
}

// 查找的数字不存在
void Test4()
{
	vector<int> data = { 1, 3, 3, 3, 3, 4, 5 };
	Test("Test4", data, 2, 0);
}

// 查找的数字比第一个数字还小,不存在
void Test5()
{
	vector<int> data = { 1, 3, 3, 3, 3, 4, 5 };
	Test("Test5", data, 0, 0);
}

// 查找的数字比最后一个数字还大,不存在
void Test6()
{
	vector<int> data = { 1, 3, 3, 3, 3, 4, 5 };
	Test("Test6", data, 6, 0);
}

// 数组中的数字从头到尾都是查找的数字
void Test7()
{
	vector<int> data = { 3, 3, 3, 3 };
	Test("Test7", data, 3, 4);
}

// 数组中的数字从头到尾只有一个重复的数字,不是查找的数字
void Test8()
{
	vector<int> data = { 3, 3, 3, 3 };
	Test("Test8", data, 4, 0);
}

// 数组中只有一个数字,是查找的数字
void Test9()
{
	vector<int> data = { 3 };
	Test("Test9", data, 3, 1);
}

// 数组中只有一个数字,不是查找的数字
void Test10()
{
	vector<int> data = { 3 };
	Test("Test10", data, 4, 0);
}

// 鲁棒性测试,数组空指针
void Test11()
{
	Test("Test11", vector<int>(), 0, 0);
}

int main(int argc, char* argv[])
{
	Test1();
	Test2();
	Test3();
	Test4();
	Test5();
	Test6();
	Test7();
	Test8();
	Test9();
	Test10();
	Test11();

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值