对应letecode链接:
力扣
题目描述:
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2限制:
1 <= 数组长度 <= 50000
方法1:排序
既然数组中有出现次数
> ⌊ n/2 ⌋
的元素,那排好序之后的数组中相同的元素总是相邻的即存在长度
> ⌊ n/2 ⌋
的一长串由相同元素构成的连续子数组那么中间元素一定是出现次数大于n/2的元素举个例子:无论是
1 1 1 2 3
,0 1 1 1 2
还是-1 0 1 1 1
,数组中间的元素总是“多数元素”,毕竟它长度> ⌊ n/2 ⌋
。
对应代码:
class Solution { public:int majorityElement(vector<int>& nums) {sort(nums.begin(),d());//排序return nums[nums.size()/2];} };
但是这样的时间复制度是0(N*logN)
方法二:hash表
直接遍历整个 数组 ,将每一个数字(num)与它出现的次数(count)存放在 哈希表 中,同时判断该数字出现次数是否是最大的,动态更新 maxCount,最后输出 maxNum。
对应动图:
对应代码:
class Solution { public:int majorityElement(vector<int>& nums) {int maxCount=0;int maxNum=0;unordered_map<int,int>hash;for(auto x:nums){hash[x]++;if(hash[x]>maxCount){//更新出现次数最多的数字maxCount=hash[x];maxNum=x;}}return maxNum;//返回结果} };
方法三:摩尔庄园投票
对应思想:
我们遍历投票数组,将当前票数最多的候选人与其获得的(抵消后)票数分别存储在 major 与 count 中。
当我们遍历下一个选票时,判断当前 count 是否为零:
若 count == 0,代表当前 major 空缺,直接将当前候选人赋值给 major,并令 count++
若 count != 0,代表当前 major 的票数未被完全抵消,因此令 count--,即使用当前候选人的票数抵消 major 的票数
以
[2,2,1,3,1,2,2]
为例。遍历数组第一个元素
2
时,因major
空缺,所以赋值major = 2
,且票数count = 1
:
我们发现第二个元素依旧是「候选人」
2
,与major
相同,因此将票数加一:
第三个元素是
1
,与major
不同,因此发生「对抗」,将当前major
的票数冲抵掉 1 票:
第四个元素是
3
,又与major
不同,因此产生「对抗」,票数继续冲抵:
当遍历到第五个元素
1
时,我们发现当前count
已经归0
,说明major
位置空缺,因此我们令major = 1
,且count = 1
:
第六个元素是
2
,与major
不同,因此进行票数抵消,元素1
刚上位又要下台了:
此时
count
又归零了,因此当遍历到最后一个元素2
时,令major = 2
,票数count = 1
:
遍历结束求出多数元素为2
对应代码:
class Solution { public:int majorityElement(vector<int>& nums) {int major = 0;int count = 0;for(auto x:nums){if(count==0){major=x;}if(x==major){count++;//相同则++}else{count--;//不相同则--;}}return major;} };
对应letecode链接:
力扣
题目描述:
给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。
示例 1:
输入:[3,2,3]
输出:[3]
示例 2:输入:nums = [1]
输出:[1]
示例 3:输入:[1,1,1,3,3,2,2,2]
输出:[1,2]提示:
1 <= nums.length <= 5 * 104
-109 <= nums[i] <= 109
方法一哈希表:
由于在上面已经说过了在这里就不赘述了直接给出代码:
对应代码:
class Solution { public:vector<int> majorityElement(vector<int>& nums) {int n=nums.size();unordered_map<int,int>hash;vector<int>ans;//保存答案for(auto x:nums){hash[x]++;}for(auto x:hash){if(x.second>n/3){//如果是则放入hash表中ans.push_back(x.first);}}return ans;} };
方法二:
我们一次在数组中删掉k个不同的数,一直不停的删除直到剩下的数不足k个就停止,如果一个数在数组中出现的次数大于n/k那么它一定会留下来:
注意:这里有很重要的事实那就是出现次数大于n/k的数最多有k-1个比如出现次数大于n/3的最多只有两个
废话不多说来看代码:
class Solution { public:vector<int> majorityElement(vector<int>& nums) {unordered_map<int, int>hash;for (auto x : nums) {if (unt(x)) {//如果在hash里面直接将其出现的次数++;hash[x]++;}else {hash[x]++;//不在里面则插入if (hash.size() == 3) {//hash表满了开始删数据auto it = hash.begin();while (it != d()) {if (--it->second==0) {it = ase(it);//防止迭代器失效}else{it++;}}}}}vector<int>ans;//保存答案for(auto &x:hash){x.second=0;//将hash表中剩下的数出现的次数全部置成0;}for(auto x:nums){if(hash.find(x)!d())//如果在hash表中则将其出现的次数++hash[x]++;}for(auto x:hash){if(x.second>nums.size()/3){//检查出现的次数是否大于n/3;ans.push_back(x.first);}}return ans;//返回结果 } };
注意迭代器失效问题
题目描述:
给你一个非递减的 有序 整数数组,已知这个数组中恰好有一个整数,它的出现次数超过数组元素总数的 25%。
请你找到并返回这个整数
示例:
输入:arr = [1,2,2,6,6,6,6,7,10]
输出:6提示:
1 <= arr.length <= 10^4
0 <= arr[i] <= 10^5
我们可以使用上面的模板轻松秒杀这道题:
对应代码:
class Solution { public:int findSpecialInteger(vector<int>& arr) {unordered_map<int, int>hash;for (auto x : arr) {if (unt(x)) {//如果在hash里面直接将其出现的次数++;hash[x]++;}else {hash[x]++;//不在里面则插入if (hash.size() == 4) {//hash表满了开始删数据auto it = hash.begin();while (it != d()) {if (--it->second==0) {it = ase(it);//防止迭代器失效}else{it++;}}}}}vector<int>ans;//保存答案for(auto &x:hash){x.second=0;//将hash表中剩下的数出现的次数全部置成0;}for(auto x:arr){if(hash.find(x)!d())//如果在hash表中则将其出现的次数++hash[x]++;}for(auto x:hash){if(x.second>arr.size()*0.25){//检查出现的次数是否大于n/3;ans.push_back(x.first);}}return ans[0];} };
当然由于数组是有序的这种方法不是最快的但是如果是无序的这种方法的效率是很高的
🙌🙌🙌🙌
结语:对于个人来讲,在leetcode上进行探索以及单人闯关是一件有趣的时间,一个程序员,如果不喜欢编程,那么可能就失去了这份职业的乐趣。刷到我的文章的人,我希望你们可以驻足一小会,忙里偷闲的阅读一下我的文章,可能文章的内容对你来说很简单,(^▽^)不过文章中的每一个字都是我认真专注的见证!希望您看完之后,若是能帮到您,劳烦请您简单动动手指鼓励我,我必回报更大的付出~
本文发布于:2024-01-31 12:41:11,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170667607228589.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |