LeetCode:169. Majority Element && 229. Majority Element II


找出数组中出现次数最多的数字。
记录这题是因为这题有特定的算法,叫做Boyer-Moore Majority Vote algorithm。另外,在第二题实现该算法时有一些细节需要注意。
- Majority Element
class Solution {
public:
int majorityElement(vector<int>& nums) {
if (nums.empty())
return -1;
int candidate, count = 0;
for (const int& item : nums) {
if (item == candidate)
++count;
else if (count == 0){
candidate = item;
count = 1;
}
else --count;
}
return candidate;
}
};
直观上感受这个算法就是相互抵消,最后留下谁就是谁最多。
- Majority Element II
首先直接看代码:
class Solution {
public:
vector<int> majorityElement(vector<int>& nums) {
if (nums.empty())
return vector<int>();
vector<int> ret;
int candidate1, candidate2, count1 = 0, count2 = 0;
for (const auto &item : nums) {
if (item == candidate1)
count1++;
else if (item == candidate2)
count2++;
else if (count1 == 0) {
candidate1 = item;
count1 = 1;
}
else if (count2 == 0) {
candidate2 = item;
count2 = 1;
}
else {
count1--;
count2--;
}
}
if (count(nums.begin(), nums.end(), candidate1) > nums.size()/3)
ret.push_back(candidate1);
if (count(nums.begin(), nums.end(), candidate2) > nums.size()/3)
ret.push_back(candidate2);
return ret;
}
};
这个实现中有些细节需要注意。
1.最后还需要确保一下这个数字出现的次数,否则会出错。
2.如果不仔细看这段代码的话,会有这样的疑问:如果有个数字出现的次数刚超过1/3,少于1/2,其余数字都不相同,那么这个数字不是会被抵消完吗?比如:1,1,1,2,3,4,5,6.最后1的count不是会被抵消完吗?其实不然,需要注意的是,在代码的实现中,我们在count减1之后没有测试该count是否为0,而是留到下一轮才测试,这样的一个后果是对于1的count,我们有两个不是1的数字出现,才会对该count减1.比如,迭代完1,1,1,2之后,[candidate1,count1,candidate2,count2]的值为[1,3,2,1],迭代完3之后为[1,2,2,0],迭代完4之后为[1,2,4,1],所以,迭代了两个不是1的数,count1才减少了1.
也就是说,对于不是待选的那些数,出现两次才会抵消掉待选的那些数一次,所以对于这次选出出现次数大于1/3的,是有效的。
浙公网安备 33010602011771号