1. 问题描述:
假设有个整型数组inputArray,共有N个元素。我们要统计每个元素出现的频率。
2. 分析:
这个问题的难点在于保存每个元素的当前频率值。
比如元素1,当前出现1次了,怎么保存这个状态,解决了这个问题后,再遇到1就更新这个状态就好了,其它元素也是一样的道理。
如果用Java来解决这个问题会很简单,因为Java丰富的容器类为我们提供了上面问题的解决方案,HashMap。我们只须以这个元素为key,其出现频率为value,
后续更新它的value就可以了,而且效率还不错。
但是如果要用C语言来实现的话,一切都须得我们自己来手动解决了,这也是这篇博客的目的。
C语言解决思路:
- 首先我们声明一个大小和inputArray一样的数组countryArray,并将每个元素值初始化为-1,用来存储每个元素的频率。这需要一些技巧来达到和HashMap一样的效果却也不损失太多性能。
- if countArray[i] == -1,表示我们还没有统计inputArray[i]这个元素的频率; if countArray[i] == 0,表示我们已经统计过元素inputArray[i]的频率了。
- 用循环遍历InputArray,from 0 到 N-1,统计每个元素的频率。
- 对于当前元素inputArray[i],if countArray[i] == -1,我们就保存这个元素的频率到countArray[i];否则,不保存,因为之前已经统计过它了。
大致的过程可用下图表示:
统计数组所有元素初始值为-1,在统计过程中这些元素可能存在三种类型的值,分别表示待统计数组中对应元素的三种状态:未统计(-1)、已统计(0)、出现频率(非0,非-1)。
时间复杂度最坏:O(n^2),即每个元素只出现一次;空间复杂度:O(n),为统计数组的开销。其中n为待统计元素总个数。
代码如下:
/*
* C Program to count frequency of each Array element
*/
#include <stdio.h>
int main()
{
int inputArray[100], countArray[100];
int elementCount, i, j, count;
printf("Enter Number of Elements in Array\n");
scanf("%d", &elementCount);
printf("Enter %d numbers\n", elementCount);
/* Read array elements */
for(i = 0; i < elementCount; i++) {
scanf("%d", &inputArray[i]);
countArray[i] = -1;
}
/*
* for any element inputArray[i], If countArray[i] = -1,
* that means frequency is not counted for this number yet
* and countArray[i] = 0 means frequency is already
* counted for this number.
*/
for(i = 0; i < elementCount; i++) {
//开始统计inputArray[i]这个元素的出现频率
//至少出现1次
count = 1;
// 值为0表示该数字已经被统计过
if (countArray[i] == 0) {continue;}
for(j = i+1; j < elementCount; j++) {
if(inputArray[i]==inputArray[j]) {
countArray[j] = 0;
count++;
}
}
//记录inputArray[i]出现的频率
countArray[i] = count;
}
/* Print count of each element */
for(i = 0; i<elementCount; i++) {
if(countArray[i] != 0) {
printf("Element %d : Count %d\n", inputArray[i], countArray[i]);
}
}
return 0;
}
还想到一种更快的方式:
- 1 先对待统计数组进行排序,时间复杂度最快可达:O(nlogn)
- 2 一次遍历排序后数组,每当出现数值变动时就完成了这个数的统计。
实现代码略。