题目:
数组中占比超过一半的元素称之为主要元素。给定一个整数数组,找到它的主要元素。若没有,返回-1。
示例1
输入:[1,2,5,9,5,9,5,5,5]
输出:5
示例2
输入:[3,2]
输出:-1
示例3
输入:[2,2,1,1,1,2,2]
输出:2
说明
你有办法在时间复杂度为 O(N),空间复杂度为 O(1) 内完成吗?
class Solution {
public:
int majorityElement(vector<int>& nums) {
}
};
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/remove-element 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题方法:
自解
思路:先排序,再对相邻的相同数据进行计数
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(),nums.end());
if(nums.size() == 1)
return nums[0];
int count = 1;
for(int i=1; i < nums.size(); i++){
if(nums[i] == nums[i-1]){ // 相邻两数相等,计数++
count++;
if(count / float(nums.size()) > 0.5)
return nums[i];
}
else // 相邻两数不等,重新开始计数
count = 1;
}
return -1;
}
};
解法1
分析:主要元素在数组中占比超过一半,若数组有序,则主要元素应当满足:某一位置的元素与其位置距离超过数组长度一半位置的元素相同。
思路:先排序,再逐个判断一个位置上的元素与其位置距离超过数组长度一半的元素是否相等。
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(),nums.end());
int haflen = nums.size() / 2;
for(int i=0; i + haflen < nums.size(); i++){
if(nums[i] == nums[i + haflen])
return nums[i];
}
return -1;
}
};
时间复杂度:O(nlogn)
空间复杂度:O(1)
解法2
分析:主要元素在数组中占比超过一半,即主要元素的个数超过数组总长度的一半,表明核心在于计数,可以采用一种数据结构直接实现计数共功能——哈希表。
思路:以数据中的数作为key,该数出现次数作为value构建哈希表。
class Solution {
public:
int majorityElement(vector<int>& nums) {
unordered_map<int,int> hashmap;
for(auto x : nums){
hashmap[x]++;
if(hashmap[x] > nums.size() / 2)
return x;
}
return -1;
}
};
时间复杂度:O(n)
空间复杂度:O(n)
注意:STL中哈希表的基本用法
-
定义:
unordered_map<keyType, valueType> mapName;
-
插入:
emplace():如果key元素是唯一的,在unordered_map中插入新元素
mapName.emplace(key, value);
insert():直接插入元素类型,返回pair类型,返回值pair第一元素是插入元素迭代器,第二元素表示操作是否成功:
*插入pair 数据:
mapname.insert(pair<int, string>(3, "pankun"))
*插入value_type数据:
mapname.insert(map<int, string>::value_type(3, "pankun")
-
查询:
at():根据Key值查找容器内元素,并返回map元素的引用
mapName.at( key);
find():查找函数,通过key查找一个元素,返回迭代器类型。
mapName.find(key);
count():某个key值对应的map(value)值的数量,因为unordered_map不允许重复元素,所以返回值总是0或1(0表示哈希表中不存在当前key,1表示哈希表中存在当前key,可用于判断哈希表中是否存在某个key值)
mapName.count(key);
-
迭代:
begin():指向容器内第一个元素的迭代器。end():指向容器内最后一个元素的后一个位置的迭代器
map<int, string>::iterator iter; for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
迭代器访问元素时,it->first对应key,it->second对应map(value) -
删除:
earse():根据不同的索引擦除插槽中的元素
mapName.earse(key);
mapName.earse(iterator_position);
mapName.earse(iterator_first, iterator_last);
-
运算符重载:
‘=’ 运算符重载‘[ ]’ 操作符重载
mapName[key];
解法3(!!!) 摩尔计数法
分析:本道题中的主要元素一定是众数,但是众数不一定是主要元素。
可先找出数组中的众数,再判断众数是否为主要元素。
如何找众数?找众数的核心就是计数,一种比较好的计数方法是初始化一个众数,若数组元素与众数不同,则抵消一个众数,若数组元素与众数相同,则增加一个众数的计数。
思路:首先用一个计数器count 遍历一遍数组寻找众数major:
> 元素与众数相同,则计数增加,元素与众数不相同,则相互抵消。
> 若最后计数count >0,则众数可能是我们需要的数
> 还需遍历一遍数据对众数进行判断:众数在数组中的个数是否大于数组元素数目的一半、
class Solution {
public:
int majorityElement(vector<int>& nums) {
int major, count=0;
for(int x : nums){ // 找众数
if(count == 0){
major = x;
}
if(major == x){
count++;
else
count--;
}
if(count > 0){ // 判断众数是否为主要元素
int count1=0;
for(int y : nums){
if(y == major){
count1++
if(count1 > nums.size() / 2)
return mejor;
}
}
}
return -1;
}
};