标签:leetcode 多数元素 moore c++ 分布式
https://leetcode.com/problems/majority-element/
Difficulty: Easy
查找数组的多数元素(majority element)
多数元素为数组中出现次数多于
LeetCode的解答中给出了七种思路
第一种是Brute force solution,时间复杂度为
第二种是Hash table,时间复杂度为
第三种是Sorting,时间复杂度为
第四种是Randomization,平均时间复杂度为
// Runtime: 20 ms
#include <cstdlib>
class Solution {
public:
int majorityElement(vector<int>& nums) {
int size = nums.size();
while (true) {
int r = nums[rand() % size];
int count = 0;
for (int i = 0; i < size; i++) {
if (r == nums[i]) {
count++;
}
}
if (count > size >> 1) {
return r;
}
}
}
};
第五种是Divide and conquer,时间复杂度为
第六种是Moore voting algorithm,时间复杂度为
// Runtime: 16 ms
class Solution {
public:
int majorityElement(vector<int>& nums) {
int maj = nums[0], count = 1;
for (int i = 1; i < nums.size(); i++) {
if (count == 0) {
maj = nums[i];
count++;
}
else if (maj == nums[i]) {
count++;
}
else {
count--;
}
}
return maj;
}
};
第七种是Bit manipulation,时间复杂度为
https://leetcode.com/problems/majority-element-ii/
Difficulty: Medium
查找数组中出现次数多于
类似于 Majority Element 中的第六种算法Boyer-Moore Majority Vote Algorithm,由于最多有两个可能的元素,所以我们使用两个 candidate,每个 candidate 对应一个 counter。Majority Element 中若两个元素不同,则去除这两个元素并不影响剩余数组的多数元素。类似的,在本题中,如果去除三个不同的元素,并不影响剩余数组的出现次数多于
需要注意的是,循环中判断的顺序很重要,需要先判断当前元素是否与两个 candidate 之一相匹配,若均不匹配,再判断 counter。这就需要考虑,最初的 candidate 需要如何确定。即便数组的长度大于等于2,依旧不能类似 Majority Element 那样,使用数组的前两个元素作为两个 candidate,因为数组的前两个元素可能是相同的。其实解决办法也很简单,只要给两个 candidate 赋予不同的初值,并且两个 counter 的初值均为 0 即可。
如果先判断 counter,则有可能出现两个 candidate 相同的情况。如测试用例
class Solution {
public:
vector<int> majorityElement(vector<int>& nums) {
vector<int> ret;
int n1 = 0, n2 = 1, count1 = 0, count2 = 0;
for (auto n: nums) {
if (n == n1) {
count1++;
} else if (n == n2) {
count2++;
} else if (count1 == 0) {
n1 = n;
count1 = 1;
} else if (count2 == 0) {
n2 = n;
count2 = 1;
} else {
count1--;
count2--;
}
}
if (count1 != 0 && validateME(nums, n1)) {
ret.push_back(n1);
}
if (count2 != 0 && validateME(nums, n2)) {
ret.push_back(n2);
}
return ret;
}
bool validateME(vector<int>& nums, int val) {
int count = 0;
for (auto n: nums) {
if (n == val) {
count++;
}
}
if (count > nums.size() / 3) {
return true;
} else {
return false;
}
}
};
Boyer-Moore Majority Vote Algorithm 中给出了两个扩展,一是使用更少的比较次数,一是如何并行执行这个算法
在不确定多数元素是否存在的情况下,使用 Boyer-Moore 算法找到的 candidate 还需要遍历一次数组对其出现次数进行计数。在最坏情况下需要比较
核心思想是重新排列元素确保相邻元素不同。
第一遍,维护一个空的 rearranged list 和一个空的 bucket。遍历数组,并与 list 的最后一个元素相比,若相同,则把该元素放入 bucket 中,若不同,则放入 list 中,然后取 bucket 的一个元素也放入 list 中。遍历完成后,list 的最后一个元素即为备选的 candidate
第二遍,一次用 list 的最后一个元素与 candidate 比较,若相同,则删除 list 的最后两个元素,若不同,则删除 list 的最后一个元素和 bucket 中的一个元素。如果移除了 list 的所有元素并且 bucket 不空,则 candidate 是多数元素。(很多边界条件需要考虑,但大体思想如此。举一个实际的例子基本就理解了这个算法。比如 5 5 0 0 5,最后 list 剩余 5,而 bucket 为空,这也算是 candidate 为多数元素的一种情况)
举个例子,5(1) 5 (2) 0(1) 0(2) 0(3) 5(3) 0(4) 0(5) 5(4),这里只给出第一遍遍历的情况,第二遍按照思想,很容易走通
iterator | list | bucket |
---|---|---|
1 | 5(1) | |
2 | 5(1) | 5(2) |
3 | 5(1) 0(1) 5(2) | |
4 | 5(1) 0(1) 5(2) 0(2) | |
5 | 5(1) 0(1) 5(2) 0(2) | 0(3) |
6 | 5(1) 0(1) 5(2) 0(2) 5(3) 0(3) | |
7 | 5(1) 0(1) 5(2) 0(2) 5(3) 0(3) | 0(4) |
8 | 5(1) 0(1) 5(2) 0(2) 5(3) 0(3) | 0(4) 0(5) |
9 | 5(1) 0(1) 5(2) 0(2) 5(3) 0(3) 5(4) 0(4) | 0(5) |
保留每个处理结果的 candidate 和 counter,对所有的结果再执行一次 Boyer-Moore 算法。需要注意的是,这次不是单纯的增减一了,而是根据需要比较元素的 counter 来进行处理。这里的代码引自原文,虽然是用 Python 写的,但是一目了然。
candidate = 0
count = 0
for candidate_i, count_i in parallel_output:
if candidate_i = candidate
count += count_i
else if count_i > count:
count = count_i - count
candidate = candidate_i
else
count = count - count_i
版权声明:本文为博主原创文章,未经博主允许不得转载。
Majority Element && Majority Element II
标签:leetcode 多数元素 moore c++ 分布式
原文地址:http://blog.csdn.net/novostary/article/details/47680171