在数组中求主元素(在数组中超过数组长度 的元素)
解决方案:摩尔投票法——简单来说就是由于(主元素个数-其余元素个数)>0,所以两个不同的数可以一起删掉,留下的就是主元素
算法流程:
cnt=0
major=0
for num in nums loop
//相等则+1
if num==major then
cnt=cnt+1
else if cnt==0 then
cnt=cnt+1
//假设为主元素
major=num
else
//抵消
cnt=cnt-1
end
end
cnt=0
//查看major真正出现次数
for num in nums loop
if num==major then
cnt=cnt+1
end
//确认是否真的超过了1/2
if cnt>floor(nums.size()/2) then
return major
else
return -1
end
关于为什么要确认真的超过了一半,举个例子:
数组: [4, 1, 3, 8, 3, 5, 9, 1, 3, 3]
cnt变化: [1, 0, 1, 0, 1, 0, 1, 0, 1, 2]
数组排序后:[1, 1, 3, 3, 3, 3, 4, 5, 8, 9]
可以看得出最后认为的主元素是3,但是实际上3只出现了4次,而数组长度为10,没有超过一半
oj
leetcode169
LintCode46
leetcode AC代码
class Solution {
public:
int majorityElement(vector& nums) {
int cnt=0,major=0;
for(int &num:nums){
if(major==num){
++cnt;
}
else if(cnt==0){
++cnt;
major=num;
}
else{
--cnt;
}
}
return major;
}
};
数组中找到所有超过数组长度 的
解决方案:与问题1类似,由于数组中超过数组长度1/3的不会超过3-1=2个,所以我们可以用两个计数器来记录,其他的类似
oj
leetcode229
lintcode47
leetcode AC代码
class Solution {
public:
vector majorityElement(vector& nums) {
vector result;
if (nums.size() == 0)return result;
int major1 = 0, major2 = 0, cnt1 = 0, cnt2 = 0;
for (int &num : nums) {
if (num == major1) {
++cnt1;
}
else if (num == major2) {
++cnt2;
}
else if (cnt1 == 0) {
major1 = num;
++cnt1;
}
else if (cnt2 == 0) {
major2 = num;
++cnt2;
}
else {
--cnt1;
--cnt2;
}
}
cnt1 = 0, cnt2 = 0;
for (int &num : nums) {
if (num == major1)++cnt1;
else if (num == major2)++cnt2;
}
int size=nums.size()/3;
if (cnt1 > size)result.push_back(major1);
if (cnt2 > size)result.push_back(major2);
return result;
}
};
数组中找到所有超过数组长度 的
解决方案:其实有了前两问,这个就很自然地就能想出来方法
oj
LintCode48
AC代码
//其实lintcode只让你找一个,但是找所以处理方法和问题2类似
class Solution {
public:
/**
* @param nums: A list of integers
* @param k: An integer
* @return: The majority number
*/
int majorityNumber(vector &nums, int k) {
// write your code here
int* major=new int[k];
int* cnt=new int[k];
memset(cnt,0,k*sizeof(int));
memset(major,0,k*sizeof(int));
for(int &num:nums){
bool flag=false;
for(int i=0;inums.size()/k){
return major[i];
}
}
}
};