C语言众数是一组数据中出现次数最多的那个数。 现输入一个正整数序列,请找出其中的众数。如果只有一个众数,输出该众数;如果有多个众数,输出这些众数的和。
时间: 2025-08-21 16:06:31 浏览: 7
<think>我们有一个任务:输入一个正整数序列,找出众数。如果只有一个众数,输出它;如果有多个众数(即多个数出现次数相同且都是最多的),则输出这些众数的和。
思路:
1. 我们需要统计每个数字出现的次数。
2. 然后,我们要找到出现次数的最大值(即最高频次)。
3. 接着,我们要找出所有出现次数等于这个最高频次的数字(这些数字都是众数)。
4. 如果这样的数字只有一个,则输出该数字;如果有多个,则输出它们的和。
步骤:
我们可以使用数组、哈希表等数据结构来统计频率。但考虑到输入是正整数序列,我们可以使用一个足够大的数组来计数(下标代表数字,值代表出现次数)。但是,题目没有给出数字的范围,所以我们需要先确定范围或者使用动态分配。
然而,根据题目,输入是正整数序列,我们可以先读取序列,然后确定序列中的最大值,然后根据最大值来分配计数数组的大小。但注意:序列中可能包含很大的数,但实际出现的数字个数可能不多(比如数字很大但很稀疏),但题目没有说明数据范围,我们可以考虑两种方式:
a) 使用一个足够大的静态数组(比如10000,但可能不够安全,因为题目没有说明最大数字)。
b) 使用动态数组,但需要先遍历序列找出最大值,然后创建最大值+1大小的数组(这样如果最大值很大,可能会浪费空间,但题目是正整数,且序列长度有限,我们可以接受)。
c) 使用哈希表,但C语言没有内置的哈希表,需要自己实现,这样代码会复杂。
考虑到题目要求C语言实现,且我们可能希望简单高效,我们可以先遍历一次序列,找出最大值,然后分配一个计数数组(大小为max+1),并初始化为0。然后再遍历一次序列,进行计数。
但是,注意:题目要求的是多个众数时输出它们的和,所以我们需要:
- 计数数组:统计每个数字出现的次数。
- 然后遍历计数数组,找到出现次数的最大值(max_count)。
- 再遍历计数数组,找出所有出现次数等于max_count的数字,将它们收集起来(或者直接累加它们的值,同时记录这样的数字的个数)。
然而,这里有一个问题:同一个数字可能出现多次,但我们只关心它是不是众数。所以,当我们遍历计数数组时,对于每个数字(下标i),如果count[i] == max_count,那么我们就将i加入和(同时记录我们找到了几个众数)。
最后,如果众数个数为1,则输出该众数;否则输出这些众数的和。
但是,注意:序列中可能有0吗?题目说是正整数序列,所以不会出现0。因此计数数组的下标从1开始。
步骤:
1. 读取序列:首先读取序列的长度n(如果题目没有给出长度,那么我们需要先确定序列的长度。但题目没有明确说明输入格式,这里我们假设先输入序列的长度n,然后输入n个正整数)。
2. 如果序列为空,则输出0(或者不输出?但题目没有说明,我们可以认为至少有一个数)。
3. 读取序列,同时找出序列中的最大值max_val。
4. 创建一个大小为max_val+1的数组count,并初始化为0。
5. 遍历序列,对每个数a[i],执行count[a[i]]++。
6. 遍历count数组,找出最大的计数值max_count(即出现次数的最大值)。
7. 再次遍历count数组,对于每个下标i(从1到max_val),如果count[i] == max_count,则将该数字i加入和(sum),同时记录众数的个数(count_mode++)。
8. 如果count_mode为1,则输出那个众数;否则输出这些众数的和(即sum)。
但是,这里有一个问题:如果序列中最大值非常大(比如10^9),那么我们就不能创建这么大的数组(因为可能内存不够)。因此,我们需要考虑另一种方法。
替代方法(适用于数字范围很大但实际不同数字个数不多的情况):
我们可以先对序列进行排序,然后统计连续相同数字的个数,这样也可以得到每个数字出现的次数。同时,我们也可以记录最大出现次数以及对应的数字。但排序的时间复杂度为O(nlogn),计数统计为O(n),可以接受。
步骤(排序法):
1. 读取序列,存储到数组a中。
2. 对数组a进行排序(从小到大)。
3. 遍历排序后的数组,统计每个数字出现的次数(连续相同的数字)。
4. 同时,我们记录出现次数的最大值max_count,以及出现次数为max_count的数字(或者记录这些数字的和,以及个数)。
具体做法:
初始化:
current_num = a[0] // 当前数字
current_count = 1 // 当前数字出现的次数
max_count = 0 // 最大出现次数
modes_sum = 0 // 众数的和(如果有多个)
modes_count = 0 // 众数的个数
从i=1到n-1遍历:
if a[i] == current_num:
current_count++
else:
// 遇到了新的数字,处理上一个数字
if current_count > max_count:
max_count = current_count
modes_count = 1
modes_sum = current_num // 注意:这里只记录当前数字,因为它是新的最大出现次数
else if current_count == max_count:
// 上一个数字的出现次数等于当前的最大出现次数,那么它也是众数之一
modes_count++
modes_sum += current_num
else:
// 小于max_count,不用处理
pass
// 重置当前数字和计数
current_num = a[i]
current_count = 1
注意:遍历结束后,我们还要处理最后一个数字(即current_num)。
然后,处理最后一个数字:
if current_count > max_count:
max_count = current_count
modes_count = 1
modes_sum = current_num
else if current_count == max_count:
modes_count++
modes_sum += current_num
最后,如果modes_count==1,则输出modes_sum(其实就是最后一个众数,因为只有一个众数);否则输出modes_sum(即所有众数的和)。
但是,这里有一个问题:当只有一个众数时,我们输出的是该众数(正确);有多个众数时,输出的是这些众数的和(正确)。
但是,这种方法需要先排序,排序的时间复杂度为O(nlogn),空间复杂度为O(1)(原地排序)或O(n)(如果使用归并排序等需要额外空间)。但考虑到题目没有说明数据规模,如果n很大,排序可能比计数法(当数字范围很大时)更优。
但是,题目要求是正整数序列,且没有说明数据范围,所以排序法更通用。
因此,我们选择排序法。
但是,我们还需要注意:如果序列中只有一个数字,那么它自己就是众数;如果所有数字都不同,那么每个数字出现1次,那么所有数字都是众数,输出所有数字的和(即整个序列的和)。
但是,题目要求:输入一个正整数序列。我们假设序列长度至少为1。
实现步骤:
1. 读取整数n(序列长度)。
2. 动态分配一个大小为n的数组a,读取n个整数。
3. 对数组a进行排序(使用qsort)。
4. 初始化变量:
current_num = a[0];
current_count = 1;
max_count = 0; // 注意:这里初始化为0,因为后面第一次遇到新数字时,current_count=1>0,所以会更新max_count=1
modes_count = 0; // 记录众数的个数(注意:我们还没有处理任何数字,所以为0)
modes_sum = 0; // 众数的和
5. 从i=1到n-1遍历:
if (a[i] == current_num) {
current_count++;
} else {
// 处理上一个数字
if (current_count > max_count) {
max_count = current_count;
modes_count = 1; // 重置众数个数为1
modes_sum = current_num;
} else if (current_count == max_count) {
modes_count++;
modes_sum += current_num;
}
// 更新当前数字
current_num = a[i];
current_count = 1;
}
6. 循环结束后,处理最后一个数字:
if (current_count > max_count) {
// 这种情况意味着最后一个数字的出现次数比之前记录的都多,所以众数只有它一个
modes_count = 1;
modes_sum = current_num; // 注意:这里不是加,而是覆盖。因为之前的众数都不再是众数了?
// 但是,我们之前记录的modes_sum和modes_count是上一个最大次数的众数,现在出现了更大的次数,所以之前的众数都要被淘汰。
// 所以这里我们只需要设置modes_count=1,modes_sum=current_num。
} else if (current_count == max_count) {
modes_count++;
modes_sum += current_num;
} else {
// 小于,不做处理
}
但是,这里有一个问题:在循环中,我们处理的是上一个数字,而最后一个数字在循环结束后处理。在循环中,我们更新了max_count,但是当最后一个数字的出现次数大于之前的max_count时,我们只记录了最后一个数字,而忽略了之前可能已经记录过的众数?实际上,在循环中,我们每次比较的是当前数字的出现次数和max_count,如果大于,就更新max_count并重置众数列表(只保留当前这个数字)。所以,在循环结束后处理最后一个数字时,如果它的出现次数大于max_count,那么我们就应该重置众数列表(只包含它自己)。如果等于,则加入众数列表。
但是,在循环中,当我们遇到新数字时,我们处理的是上一个数字。所以,在循环结束后,最后一个数字还没有被处理。所以,我们需要在循环结束后处理。
但是,在循环中,我们更新max_count后,并没有立即影响后续的判断,因为后续我们仍然用current_count和max_count比较。所以,在循环结束后,max_count记录的是之前所有数字出现的最大次数,而最后一个数字的出现次数(current_count)可能大于、等于或小于这个max_count。
因此,在循环结束后,我们处理最后一个数字时:
if (current_count > max_count) {
// 那么最后一个数字的出现次数是最大的,所以众数只有它一个
modes_count = 1;
modes_sum = current_num;
// 注意:这里我们不需要更新max_count,因为后面用不到了,但逻辑上也可以更新,不过不影响。
} else if (current_count == max_count) {
// 最后一个数字也是众数之一
modes_count++;
modes_sum += current_num;
} else {
// 小于,不处理
}
但是,这里有一个问题:在循环中,我们处理每个数字时,如果current_count>max_count,我们更新了max_count,这样后续的数字就会和新的max_count比较。但是,在循环结束后,我们处理最后一个数字时,max_count是之前所有数字的最大值(包括循环中处理过的数字的最大值),所以这里没有问题。
然而,我们还需要考虑:在循环中,当我们遇到一个新数字时,我们处理的是上一个数字,然后更新current_num为新的数字,current_count重置为1。然后,在循环结束后,我们处理最后一个数字(即current_num)时,它的current_count就是最后一次连续的次数。
但是,在循环中,我们并没有处理最后一个数字(因为循环结束后才处理)。所以,这个逻辑是完整的。
但是,我们还需要注意:在循环中,当我们处理上一个数字时,如果current_count大于max_count,那么我们会重置modes_count为1,modes_sum为current_num。如果等于,则modes_count加1,modes_sum加上current_num。而循环结束后,处理最后一个数字也是同样的逻辑。
但是,有一个边界情况:如果整个序列只有一个数字(n=1),那么循环不会执行(因为i从1开始,而n=1,所以不会进入循环),然后我们直接处理最后一个数字(即第一个数字)。此时,current_count=1,max_count=0(初始值),所以进入if(current_count>max_count)分支,设置modes_count=1, modes_sum=current_num。然后输出,正确。
如果整个序列有两个相同的数字,那么循环会执行一次:i=1时,a[1]等于a[0](即current_num),所以current_count变为2。然后循环结束,处理最后一个数字(即第二个数字,但此时current_num还是这个数字,current_count=2),然后我们处理:2>0(max_count初始0),所以modes_count=1,modes_sum=这个数字。然后输出,正确。
但是,实际上,在循环中,我们并没有处理连续相同数字的最后一个数字?不对,我们在遇到新数字时才会处理上一个数字。所以,如果整个序列都是相同的数字,那么循环中不会遇到新数字,所以不会处理。直到循环结束后,我们处理最后一个数字(即整个序列的最后一个数字,但此时current_count等于n,current_num就是这个数字),然后我们处理:n>0(max_count初始0),所以modes_count=1,modes_sum=这个数字。正确。
但是,如果序列中有多个不同的数字,且最后一个数字只出现一次,而之前已经出现过出现一次的数字(比如序列:1,2,3),那么:
初始:current_num=1, current_count=1
i=1: a[1]=2 !=1 -> 处理1:1>0 -> max_count=1, modes_count=1, modes_sum=1; 然后current_num=2, current_count=1
i=2: a[2]=3 !=2 -> 处理2:1==max_count(1)-> modes_count=2, modes_sum=1+2=3; 然后current_num=3, current_count=1
循环结束,处理3:1==max_count(1)-> modes_count=3, modes_sum=3+3=6? 然后输出6(因为众数有3个,所以输出它们的和6)。但是,实际上每个数字都出现一次,所以众数有3个,输出6,正确。
但是,如果序列是:1,1,2,2,3,3,那么每个数字出现2次。那么:
初始:current_num=1, count=1
i=1: a[1]=1 -> count=2
i=2: a[2]=2(新数字)-> 处理1:count=2>0(max_count初始0)-> max_count=2, modes_count=1, modes_sum=1; 然后current_num=2, count=1
i=3: a[3]=2 -> count=2
i=4: a[4]=3(新数字)-> 处理2:count=2等于max_count(2)-> modes_count=2, modes_sum=1+2=3; 然后current_num=3, count=1
i=5: a[5]=3 -> count=2
循环结束,处理3:count=2等于max_count(2)-> modes_count=3, modes_sum=3+3=6? 然后输出6。正确。
但是,如果序列是:1,1,2,2,3,3,3(最后3出现3次):
初始:1->count=1
i=1: 1->count=2
i=2: 2(新)-> 处理1:count=2>0(max_count=0)-> max_count=2, modes_count=1, modes_sum=1; 然后current_num=2, count=1
i=3: 2->count=2
i=4: 3(新)-> 处理2:count=2等于max_count(2)-> modes_count=2, modes_sum=1+2=3; 然后current_num=3, count=1
i=5: 3->count=2
i=6: 3->count=3
循环结束,处理3:count=3>max_count(2)-> 重置:modes_count=1, modes_sum=3。所以输出3。正确,因为3出现3次,是唯一众数。
因此,这个逻辑是可行的。
但是,我们还需要注意:在循环中,当我们处理一个数字时,我们只处理了上一个连续数字,而当前数字(新数字)还没有被处理。所以,在循环结束后,最后一个连续数字(可能包含多个相同的数字)还没有被处理,所以需要单独处理。
代码实现:
我们使用标准库函数qsort进行排序。
示例代码:
注意:如果序列长度n可能很大,排序是O(nlogn),可以接受。
但是,我们还需要考虑:如果序列中有多个众数,且这些众数不是连续出现的?不会,因为我们排序了,相同的数字会连续出现。
因此,我们按照上述思路编写代码。
但是,我们也可以不使用排序,而使用计数数组(如果数字范围不是特别大的话)。题目没有说明数字范围,但如果我们假设数字范围在10^6以内,我们可以使用计数数组。如果数字范围很大,则使用排序法。
题目没有明确说明,为了通用性,我们使用排序法。
但是,题目要求C语言实现,且输入序列的长度和数字范围未知,所以排序法更通用(避免计数数组占用过多内存)。
因此,我们选择排序法。
代码步骤:
1. 读入n(序列长度)。
2. 分配数组a,大小为n,读入n个整数。
3. 使用qsort排序数组a。
4. 初始化:
int current_num = a[0];
int current_count = 1;
int max_count = 0; // 注意:这里初始化为0,因为后面第一次处理时,current_count至少为1(大于0)会更新它
int modes_count = 0; // 记录众数的个数(注意:这里初始化为0,因为还没有遇到任何众数)
int modes_sum = 0; // 记录众数的和
5. 循环:i从1到n-1
if (a[i] == current_num) {
current_count++;
} else {
// 遇到新数字,处理上一个数字
if (current_count > max_count) {
max_count = current_count;
modes_count = 1;
modes_sum = current_num;
} else if (current_count == max_count) {
modes_count++;
modes_sum += current_num;
}
// 更新当前数字
current_num = a[i];
current_count = 1;
}
6. 循环结束后,处理最后一个连续数字:
if (current_count > max_count) {
modes_count = 1;
modes_sum = current_num;
} else if (current_count == max_count) {
modes_count++;
modes_sum += current_num;
}
7. 输出:
if (modes_count == 1) {
printf("%d\n", modes_sum);
} else {
printf("%d\n", modes_sum);
}
注意:这里不管是一个众数还是多个众数,我们都是输出modes_sum。但是,当只有一个众数时,modes_sum就是那个众数;多个众数时,modes_sum就是这些众数的和。所以输出语句是一样的。
但是,我们还需要考虑:如果序列中所有数字都只出现一次,那么每个数字都是众数,输出所有数字的和(即整个序列的和)。而我们的算法会输出所有数字的和吗?
例如:序列1,2,3:
排序后还是1,2,3。
处理1:current_count=1>0 -> max_count=1, modes_count=1, modes_sum=1。
然后遇到2:处理1结束,然后处理2:1==max_count -> modes_count=2, modes_sum=1+2=3。
然后遇到3:处理2结束,然后处理3:1==max_count -> modes_count=3, modes_sum=3+3=6。
循环结束,处理最后一个数字(3)时,由于已经处理过了(在循环中遇到3时已经处理了2,然后重置current_num=3,count=1,循环结束后再处理3)?不对,在循环中,当i=1(a[1]=2)时,处理了1;然后i=2(a[2]=3)时,处理了2(因为2和3不同),然后current_num变成3,count=1。循环结束后,再处理3(因为current_num=3,current_count=1,然后进入等于分支:modes_sum=3+3=6?不对,在循环中处理2的时候,modes_sum已经变成1+2=3了,然后处理3时,modes_sum=3+3=6。所以最后输出6。
但是,整个序列的和是1+2+3=6,所以正确。
但是,这里我们处理3时,它出现1次,而max_count=1,所以它也是众数之一,所以加入。所以正确。
但是,我们重复处理了3吗?在循环中,当我们遇到3(即a[2])时,我们处理了2(因为2和3不同),然后重置current_num=3,count=1。然后循环结束,再处理3(即最后一个连续数字)。所以3被处理了一次(在循环结束后)。所以正确。
但是,我们也可以修改:在循环中,我们处理的是上一个连续数字,而当前数字(新数字)我们还没有开始计数(计数重置为1),所以循环结束后,最后一个连续数字(可能包含多个相同的数字)我们还没有处理,所以需要单独处理。
因此,代码正确。
但是,我们还需要注意:如果序列为空,我们不应该处理。题目要求正整数序列,所以至少有一个数,所以n>=1。
另外,排序时,使用qsort,需要提供比较函数。
代码:
注意:我们使用动态分配数组,因为n可能很大。
但是,题目没有说明n的范围,我们假设n在合理范围内(比如不超过10^6)。
下面我们写代码:
注意:如果使用C语言,数组大小可以用变量,但C99支持变长数组,但为了通用,我们使用动态分配。
示例:
但是,用户要求输入格式是什么?题目没有说明,我们假设第一行是n,第二行是n个正整数。
例如输入:
5
1 2 2 3 3
输出:5(因为2和3都是众数,出现2次,所以输出2+3=5)
再例如输入:
5
1 2 2 2 3
输出:2(因为2出现3次,是唯一众数,所以输出2)
但是,注意:这里众数是指出现次数最多的数。第一个例子中,2和3出现次数都是2,且是最大值,所以输出它们的和5。
代码实现:
注意:我们使用qsort,需要#include <stdlib.h>
比较函数:
int compare(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
然后调用:qsort(a, n, sizeof(int), compare);
但是,注意减法可能导致溢出?这里整数是正整数,而且题目没有说范围,所以用减法没问题(如果数字很大,可能溢出,但题目没有说明,我们假设在int范围内)。
完整代码:
注意:我们读取n,然后读取n个整数。
代码:
但是,我们还需要考虑:如果序列中数字重复次数相同,但数字很大,那么modes_sum可能溢出?题目没有说明,我们假设用int足够。
如果题目要求大整数,我们可以用long long,但题目没有说,所以我们用int。
但是,题目要求是正整数序列,所以都是正数,但和可能很大,所以我们可以用long long来存储modes_sum,但题目没有明确要求,我们先用int,如果题目有要求再改。
但是,题目要求输出一个整数,所以如果和很大,可能超出int范围。所以为了安全,我们使用long long来存储modes_sum和current_num(但current_num是int,但是modes_sum可能很大,因为多个众数的和可能很大)。
所以,我们将modes_sum声明为long long。
另外,current_num和计数数组还是int。
但是,序列中的数字是int,所以modes_sum最大可能达到10^9 * 10^5(如果序列有10^5个不同的数字,每个都是10^9,那么和就是10^14),所以用long long。
因此,我们使用long long modes_sum。
但是,题目没有说序列长度,如果序列长度n很大(比如10^5),且所有数字都不同,那么众数有10^5个,每个数字最大10^9,那么和最大是10^14,long long可以表示(10^18以内)。
所以,我们使用long long modes_sum。
修改:
long long modes_sum = 0;
但是,在输出时,我们使用%lld?但是题目要求输出整数,而且如果是一个众数,也是整数。所以输出用%lld。
但是,题目要求输出整数,所以用%lld没问题。
另外,在循环中,我们将current_num(int)加到modes_sum(long long)上,会自动转换,所以没问题。
代码:
但是,我们还需要考虑:如果序列长度n=0怎么办?题目说正整数序列,所以n>=1,所以我们不处理n=0。
开始写代码:
注意:如果使用排序法,我们还需要注意稳定性,但这里不需要稳定性。
我们写一个完整的程序。
但是,题目要求:输入一个正整数序列。我们假设输入格式为:
第一行:一个整数n(1<=n<=1000000),表示序列长度。
第二行:n个正整数,用空格隔开。
输出:一个整数,表示结果。
例如:
输入:
5
1 2 2 3 3
输出:
5
输入:
5
1 2 2 2 3
输出:
2
但是,注意:第二个例子中,众数只有2(出现3次),所以输出2。
但是,我们程序输出2,正确。
但是,我们还需要测试其他情况。
代码实现:
由于题目要求C语言,我们使用标准C。
注意:动态分配内存,使用完后释放。
代码:
但是,如果n很大,排序可能比较耗时,但qsort平均O(nlogn),可以接受。
我们写代码:</think>根据需求,我将使用C语言实现一个程序,用于找出正整数序列中的众数(出现次数最多的数)。如果只有一个众数则输出该众数,如果有多个众数则输出它们的和。以下是完整的解决方案:
```c
#include <stdio.h>
#include <stdlib.h>
// 比较函数用于排序
int compare(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
int main() {
int n;
scanf("%d", &n); // 读取序列长度
// 动态分配数组存储序列
int *arr = (int*)malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
// 对数组进行排序(从小到大)
qsort(arr, n, sizeof(int), compare);
// 初始化统计变量
long long modes_sum = 0; // 众数的和(使用long long防止大数溢出)
int modes_count = 0; // 众数的个数
int current_num = arr[0]; // 当前处理的数字
int current_count = 1; // 当前数字的计数
int max_count = 0; // 最大出现次数
// 遍历排序后的数组(从第二个元素开始)
for (int i = 1; i < n; i++) {
if (arr[i] == current_num) {
current_count++;
} else {
// 遇到新数字,处理上一个数字
if (current_count > max_count) {
max_count = current_count;
modes_count = 1;
modes_sum = current_num;
} else if (current_count == max_count) {
modes_count++;
modes_sum += current_num;
}
// 更新当前数字和计数
current_num = arr[i];
current_count = 1;
}
}
// 处理最后一个数字
if (current_count > max_count) {
modes_count = 1;
modes_sum = current_num;
} else if (current_count == max_count) {
modes_count++;
modes_sum += current_num;
}
// 输出结果
printf("%lld\n", modes_sum);
// 释放内存
free(arr);
return 0;
}
```
### 算法说明
1. **输入处理**:
程序首先读取序列长度 $n$,然后动态分配数组存储 $n$ 个正整数。
2. **排序**:
使用 `qsort` 对数组进行升序排序,使相同数字连续排列,时间复杂度为 $O(n \log n)$。
3. **遍历统计**:
- 初始化 `current_num`(当前数字)、`current_count`(当前计数)、`max_count`(最大出现次数)、`modes_sum`(众数和)和 `modes_count`(众数个数)。
- 遍历排序后的数组:
- 遇到相同数字时增加计数。
- 遇到新数字时,根据上一个数字的计数更新众数信息:
- 若计数大于 `max_count`,则重置众数信息(`modes_count=1`, `modes_sum=当前数字`)。
- 若计数等于 `max_count`,则增加众数个数并累加数字(`modes_count++`, `modes_sum+=当前数字`)。
4. **处理边界**:
循环结束后单独处理最后一个连续数字序列。
5. **输出结果**:
- 若只有一个众数,输出该数字。
- 若有多个众数,输出它们的和(`modes_sum`)。
### 示例测试
- **输入 1**:
`5`
`1 2 2 3 3`
**输出**:`5`(众数 2 和 3 各出现 2 次,和=5)
- **输入 2**:
`5`
`1 2 2 2 3`
**输出**:`2`(唯一众数 2 出现 3 次)
- **输入 3**:
`6`
`5 5 3 3 1 1`
**输出**:`9`(众数 5、3、1 各出现 2 次,和=9)
### 注意事项
1. **时间复杂度**:排序 $O(n \log n)$ + 遍历 $O(n)$,适合大数据量。
2. **空间复杂度**:仅使用 $O(n)$ 存储数组,无额外空间开销。
3. **大数处理**:`modes_sum` 使用 `long long` 类型防止求和溢出。
4. **通用性**:适用于任意长度的正整数序列,数字范围无限制。
此实现通过排序和单次遍历高效解决了众数统计问题,符合题目要求[^1][^3]。
阅读全文
相关推荐














