题目描述
题目来源:多数元素 - 力扣(Leetcode)
给定一个大小为 n
的数组 nums
,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋
的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入:nums = [3,2,3]
输出:3
示例 2:
输入:nums = [2,2,1,1,1,2,2]
输出:2
思路解析
遍历计数法
这种题,最容易想到的思路就是创建一个计数器,然后对有序数组的重复数据进行计数
找到新的就直接归1
,过程中如果发现计数器已经大于了数组大小的一半则直接返回
保证数组有序,那就先进行排序,直接用qsort
int intCmp(const void* p1, const void* p2){
return *((int*)p1) - *((int*)p2);
}
int majorityElement(int* nums, int numsSize){
qsort (nums, numsSize, 4, intCmp);
}
后面的逻辑判断在上面也说的很清楚了,涉及逻辑判断的代码如下
int count = 1;
int max = 0;
int i = 0;
for(i = 0; i < numsSize - 1; i++){
if(nums[i] == nums[i+1]){
count++;
}else{
if(count > max){
max = count;
count = 1;
}
if(max > numsSize/2){
return nums[i];
}
}
}
这个时候其实还有一个问题,当我们的多数元素占满了数组的后半的时候
后面的计数器就会一直count++
直到循环结束,而没有机会给max
赋值
所以我们再在最后加上一个返回语句,直接返回后半的任意元素即可。因为如果循环结束了,还没有return
的话,证明多数元素一定占据了数组的后半部分,所以直接随便返回一个即可
代码总览
int intCmp(const void* p1, const void* p2){
return *((int*)p1) - *((int*)p2);
}
int majorityElement(int* nums, int numsSize){
qsort (nums, numsSize, 4, intCmp);
int count = 1;
int max = 0;
int i = 0;
for(i = 0; i < numsSize - 1; i++){
if(nums[i] == nums[i+1]){
count++;
}else{
if(count > max){
max = count;
count = 1;
}
if(max > numsSize/2){
return nums[i];
}
}
}
return nums[i];
}
排序的妙用
实际上,当我再看这道题目的时候,我在想:排序后的多数元素一定会在一起,那么既然是多数元素,个数一定是>(numsSize/2)
的,那么是不是我只要排序后直接返回数组最中间的元素即可?
实际上是可行的,这里通过画图来解释。
这里以9
为例来解释奇数长度,可以看到此时多数元素的个数一定至少为5
,那么无论这个5
长度的数组从哪里开始,都一定会包含中间的位置。
(红色的代表多数元素)
这里再以12
为例解释偶数长度,此时多数元素个数至少为7
,那么此时多数元素就更是嚣张,直接两个位置必存在,但我们依旧直接返回中间元素即可
那么代码写起来就非常简单了,排序后直接返回中间值即可
int intCmp(const void* p1, const void* p2){
return *((int*)p1) - *((int*)p2);
}
int majorityElement(int* nums, int numsSize){
qsort (nums, numsSize, 4, intCmp);
return nums[numsSize/2];
}