Leetcode
169. Majority Element
Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.
You may assume that the array is non-empty and the majority element always exist in the array.
解法一:
暴力,两个循环;时间复杂度O(n^2),空间复杂度O(1)。
解法二:
先排序,因为结果一定存在,直接返回排序后的数组中间值;时间复杂度O(n log n),空间复杂度O(1)。
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(), nums.end());
return nums[nums.size() / 2];
}
};
解法三:
朴素的分治思想,将一个数组平均分为两部分A和B,求A和B的多数元素(Majority Element),所以原数组中的多数只可能出现在A和B的多数两个之中(若不然,假设存在一个数不是A和B的多数中的任意一个,则它在数组中出现的次数大于A和B的多数出现的次数),对两个候选的多数,在原数组中一遍遍历,统计次数,便可以得到原数组的多数。
时间复杂度O(n log n),空间复杂度O(1)。
解法四:多数投票算法(Moore majority vote algorithm)
该算法在其局部变量中维护一个序列元素和一个计数器,计数器最初为零。然后它会逐个处理序列的元素。当处理元素x时,如果计数器为零,则算法将x存储为其记忆的序列元素并将计数器设置为1。否则,它会将x与存储的元素进行比较,然后递增计数器(如果它们相等)或递减计数器(否则)。在这个过程结束时,如果序列有大多数,它将是算法存储的元素。
时间复杂度O(n),空间复杂度O(1)。
class Solution {
public:
int majorityElement(vector<int>& nums) {
int candidate = 0;
int count = 0;
for (int i = 0; i < nums.size(); ++i) {
if (candidate == nums[i]) {
++count;
} else {
if (count == 0) {
candidate = nums[i];
} else {
--count;
}
}
}
return candidate;
}
};
正确性验证:
一、若多数元素在数组中的排列顺序刚好可以让它一直维持candidate的身份(即:不会在以数组第一个元素为开头的某个子序列中,多数元素出现的次数不大于子序列长度的一半),则到最后,candidate就是多数元素;
二、若多数元素在以数组第一个元素为开头的某个子序列中,不能够维持出现的次数一值大于子序列长度的一半,则candidate会一直在变(因为其他的元素无法一直维持它的candidate身份),排除掉其余所有无法满足条件的元素,剩下来的便是满足条件的多数元素了(假设多数元素存在的前提下)。
缺陷(不针对这一题):当多数元素不存在时,该算法依然会给出一个结果(最后一个candidate)。
针对上诉缺陷的改进:将算法取得的candidate,用原数组遍历一遍,看是否是多数元素。
优点:该算法支持分治,从而能够并行,可以将数组分为两部分,分别求出两部分的candidate和各自的count,根据两个candidate的count值,可以得到原数组的多数元素。
1 https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_majority_vote_algorithm