如何在有序数组中给出指定数字出现的次数

本文探讨了一种在有序数组中高效计算指定数字出现次数的算法改进,通过二分查找优化比较次数,提高了查找效率。适用于大规模数组场景。

问题描述:如何在有序数组中给出指定数字出现的次数,例如:数组{1,2,2,2,3,4,5} 数字2的出现次数为3。

最简单的方法是遍历数组,代码如下:

#include <stdio.h>
//如何在有序数组中给出指定数字出现的次数
int binarysearch(int *a,int n,int x)
{
	int cnt=0;
	for(int i=0;i<n;i++)
	{
		if(a[i]==x)
			cnt++;
	}
	return cnt;
}
int main()
{
	int a[10]={1,2,3,4,5,6,6,6,9,10};	
	printf("%d\n",binarysearch(a,10,6));
	return 0;
}

在这里我认为可以利用数组有序来优化比较次数,希望大家讨论,题目来源某知名互联网公司实习面试题.

代码如下:

#include <stdio.h>
//如何在有序数组中给出给定数字出现的次数
int binarysearch(int *a,int low,int high,int x)
{
	int cnt=0;
	int temp;
	int mid=(low+high)/2;
	while(low<=high)
	{
		mid=(low+high)/2;
		if(a[mid]<x)
			low=mid+1;
		else if(a[mid]>x)
			high=mid-1;
		else
		{
			temp=mid;
			//程序运行到这元素x已经出现一次
			cnt++;

			while(a[++mid]==x)
				cnt++;
			while(a[--temp]==x)
				cnt++;
			return cnt;
		}

	}
	//查找失败,返回0
	return 0;
}
int main()
{
	int a[10]={1,2,3,4,5,6,6,6,9,10};	
	printf("%d\n",binarysearch(a,0,10,6));
	return 0;
}


思路:

首先二分查找找到对应元素,如果查找失败返回0,如果查找成功,记录当前位置,往两侧判断,程序结构上虽然看起来比较复杂,如果数组规模较大,效率方面有不少提升,希望有更好方法的朋友能够不吝赐教。

<think>我们有两个任务:1.找出数组中出现次数最多的数字(可能有多个数字出现次数相同且都是最大次数)2.按数字从小到大的顺序输出这些数字及其出现次数步骤:1.统计每个数字出现的次数(使用哈希表/字典)2.找出最大的出现次数(即出现次数的最大值)3.收集所有出现次数等于最大次数数字4.对这些数字进行排序(从小到大)5.输出结果(可以输出数字和对应的次数,也可以只输出数字,但题目要求输出数字从小到大,同时题目要求的是出现次数最多的数字,所以应该包括数字和出现次数?)但是问题描述是:“按从小到大的顺序输出结果”,并且要求输出的是“出现次数最多的数字”。所以我们需要输出的是数字,并且按从小到大排序。至于是否要同时输出次数?问题没有明确,但通常我们会同时给出次数,或者至少说明次数。不过问题要求是“输出结果”,而结果包括数字次数。再看问题描述:“我想寻找数组中出现次数最多的数字,并按从小到大的顺序输出结果”,这的结果应该包括数字和它的出现次数,并且按数字从小到大排序。但是,如果多个数字出现次数相同且都是最大,那么这些数字都应该被输出。因此,我们可以这样设计:方法:步骤1:遍历数组,用字典(或HashMap)统计每个数字出现的次数。步骤2:遍历字典,找到最大的出现次数(max_count)。步骤3:再次遍历字典,收集所有出现次数等于max_count的数字,放入一个列表。步骤4:对这个列表进行排序(从小到大)。步骤5:遍历排序后的列表,输出每个数字及其出现次数(或者按格式输出)。但是,我们也可以优化,比如在步骤3的时候,我们可以直接用一个列表收集这些数字,然后排序。注意:题目要求按数字从小到大排序,所以最后一步排序是必要的。另外,引用[2]中给出一个先排序再统计的方法,但是那个方法只能输出一个出现次数最多的数字(如果有多个,它输出的是排序后最后一个出现次数最多的数字?因为它在循环中不断更新,最后又用最后一项来更新,所以实际上它输出的是在数组中出现次数最多且值最大的那个?)。但我们的要求是输出所有出现次数最多的数字,并按从小到大排序。所以引用[2]的方法不满足要求。因此,我们采用哈希表统计的方法。示例代码(Python):假设输入数组为:arr=[1,2,3,3,3,3,4,5,5,5,5]这3和5都出现4次,且4次是最大次数,那么输出应该包括3和5,按从小到大排序就是3和5。代码实现:步骤:1.统计频率2.找最大频率3.收集所有频率等于最大频率的数字4.排序5.输出我们也可以不找最大频率,而是用一个列表记录当前最大频率对应的数字,然后动态更新,但这样最后还是要排序。这我们分步实现。代码:注意:如果数组为空,则输出空。实现:我们使用Python,因为题目没有指定语言,但问题描述中引用了C代码,但用户要求的是算法思路,所以用Python描述更清晰。但是,用户可能希望用多种语言?问题中没有指定,这先用Python描述,如果需要其他语言可以补充。以下是Python代码:</think>要高效地找出数组中出现次数最多的数字并按从小到大排序输出,可以结合哈希统计和排序算法。以下是详细步骤和代码实现: ### 算法步骤 1. **统计频率**:使用哈希表记录每个数字的出现次数 2. **找出最大频率**:遍历哈希表找到最高出现次数 3. **收集高频数字**:找出所有出现次数等于最大频率的数字 4. **排序输出**:对高频数字进行升序排序后输出 ```python from collections import defaultdict def find_most_frequent_sorted(arr): if not arr: return [] # 1. 统计频率 freq_map = defaultdict(int) for num in arr: freq_map[num] += 1 # 2. 找出最大频率 max_freq = max(freq_map.values()) # 3. 收集高频数字 most_frequent = [num for num, count in freq_map.items() if count == max_freq] # 4. 排序输出 most_frequent.sort() return most_frequent, max_freq # 示例使用 arr = [3, 1, 4, 4, 5, 2, 3, 4, 1, 2, 4, 3] numbers, count = find_most_frequent_sorted(arr) print(f"出现次数最多的数字: {numbers}") print(f"出现次数: {count}") print("从小到大排序: " + ", ".join(map(str, numbers))) ``` ### 代码解析 1. **频率统计**:使用`defaultdict`高效统计每个数字出现次数 ```python freq_map = defaultdict(int) for num in arr: freq_map[num] += 1 ``` 2. **找出最大频率**:$O(n)$时间复杂度 ```python max_freq = max(freq_map.values()) ``` 3. **收集高频数字**:列表推导式筛选出现次数等于最大频率的数字 ```python most_frequent = [num for num, count in freq_map.items() if count == max_freq] ``` 4. **排序输出**:$O(k\log k)$时间复杂度(k为高频数字) ```python most_frequent.sort() ``` ### 时间复杂度分析 | 步骤 | 时间复杂度 | 空间复杂度 | |------|------------|------------| | 频率统计 | $O(n)$ | $O(n)$ | | 找最大频率 | $O(n)$ | $O(1)$ | | 收集高频数字 | $O(n)$ | $O(k)$ | | 排序输出 | $O(k\log k)$ | $O(k)$ | | **总计** | $O(n + k\log k)$ | $O(n)$ | > **注意**:当所有数字出现次数相同($k=n$)时,时间复杂度退化为$O(n\log n)$,但实际场景中$k$通常远小于$n$。 ### 示例输出 对于输入 `[3, 1, 4, 4, 5, 2, 3, 4, 1, 2, 4, 3]`: ``` 出现次数最多的数字: [3, 4] 出现次数: 4 从小到大排序: 3, 4 ``` ### 优化技巧 1. **大数组处理**:使用堆代替排序 ```python import heapq # 仅需前m个高频元素时 return heapq.nsmallest(m, most_frequent) ``` 2. **并行统计**(超大据集): ```python from concurrent.futures import ThreadPoolExecutor # 分段统计后合并结果 ``` 3. **内存优化**:使用计排序当数字范围有限时 ```python # 假设数字范围[0, 1000] counter = [0] * 1001 for num in arr: if 0 <= num <= 1000: counter[num] += 1 ``` 此方法结合了哈希表的高效统计和排序算法的有序输出,既满足了频率统计需求,也保证了结果的有序性[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值