前言
题目很简单,写了一下飞速通过了,但看了一下题解发现其他思路有点意思,所以记录一下。
一、题目
二、方法
1.排序取下标为n/2的元素
首先进行排序。
(n/2是取整操作)
- 如果是奇数的情况,那么nums[n/2]就是数组的正中间的那个元素,因为多数元素的个数是>n/2,所以不管多数元素是在左半区还是右半区,nums[n/2]都是多数元素,否则就不符合题意了;
- 如果是偶数的情况,首先为了满足题意,不可能出现两个数字各占一半这个情况。那么nums[n/2]这个元素位于数组一半的后一个,一定是多数元素。
代码如下(示例):
int majorityElement(int* nums, int numsSize){
//先排序
int cmp(const void* a, const void* b){
return (*(int*)a - *(int*)b);
}
qsort(nums, numsSize, sizeof(int), cmp);
//下标为n/2的元素一定是多数元素
return (nums[numsSize/2]);
}
2.哈希表(TBC)
其实哈希表对于这种类似问题还挺好使的,写在这里提醒自己掌握这种方法。
代码如下(示例):
3.摩尔投票算法(Boyer-Moore 投票算法)
摩尔算法主要用于求解众数,求解众数不是很难,但是使用常数级空间确实比较难的,可以说是一种很巧妙的算法.
摩尔算法是一种用来寻找一组元素中占多数元素的常数空间级时间复杂度算法。这一算法由罗伯特·S·博耶和J·斯特罗瑟·摩尔在1981年发表,也是处理数据流的一种典型算法。
根据摩尔投票算法所说,我们可以简单抽象为以下数学模型:
已知一组长度为n的数据arrays,求出其中元素占比较多的元素们。(通常占比会是1/2以上,1/3以上等等)。
这里我们需要理解摩尔投票中何为占多数元素,也就是元素总占比超过一个比例:
- 如果是选出占比最多的一个元素,那么占比需要是大于1/2。
- 如果是选出占比最多的两个元素,那么各个元素占比均需要大于1/3。
- 如果是选出占比最多的m个元素,那么各个元素占比需要是大于1/(m + 1)。
(以上部分参考:数据结构与算法之摩尔投票算法)
算法步骤:
- 选择一个候选数字cand,进行初始化(cand=nums[0]),将他出现的次数记为count,初始化为count=0.
- 遍历整个数组
对于数组的每个元素nums[i],都有:
(1)首先判断count此时是否为零,如果为0,则首先将nums[i]赋值给cand;
(除了刚开始的count为0是初始化,后面每次count为零,都代表着你候选为多数元素的数字和其他非候选数字出现的次数相等了,这时候就不符合多数元素的条件了,所以需要重新选一个候选数字,即重新给cand赋值。)
(2)判断完count是否为0后,开始判断nums[i]与cand:相同+1;不同-1
(3)遍历完后,cand的值就是多数元素。
以上,可以总结出,摩尔投票算法的核心算法就是“相互抵消”
举个栗子:
以数组[1,3,2,3,2,3,3]为例子,每一步操作如下:
代码实现如下:
int majorityElement(int* nums, int numsSize){
int count = 0;
int cand = nums[0];
for(int i =0; i<numsSize; i++){
if(count == 0){cand = nums[i];}
if(cand == nums[i]){count++;}
if(cand != nums[i]){count--;}
}
return cand;
}