一. 题目描述
Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋
times. The algorithm should run in linear time and in O(1)
space.
Hint:
How many majority elements could it possibly have?
二. 题目分析
题目大意是,给定一个大小为n
的整数数组,从中找出所有出现次数超过 ⌊ n/3 ⌋
的元素。要求算法满足线性时间复杂度和O(1)
的空间复杂度。
提示:一共可能有多少个majority elements?
首先应该意识到一点: 在一个数组中出现超过三分之一次的元素,这样的元素最多只能有两个,超过两个就与命题相矛盾。该题与题目Majority Element的思路相类似,只是该题中最多可能出现两个majority elements。在这里,要求线性时间复杂度和O(1)
的空间复杂度,唯有使用摩尔投票法的思想来解。
摩尔投票法的基本思想很简单,在每一轮投票过程中,从数组中找出一对不同的元素,将其从数组中删除。这样不断的删除直到无法再进行投票,如果数组为空,则没有任何元素出现的次数超过该数组长度的一半。如果只存在一种元素,那么这个元素则可能为目标元素。
三. 示例代码
// C++代码
class Solution {
public:
vector<int> majorityElement(vector<int>& nums) {
vector<int> result;
if (nums.size() == 0) return result;
int num1 = INT_MAX, num2 = INT_MAX;
int time1 = 0, time2 = 0;
for (int i = 0; i < nums.size(); ++i)
{
if (num1 == nums[i]) ++time1;
else if (num2 == nums[i]) ++time2;
else if (time1 == 0)
{
time1 = 1;
num1 = nums[i];
}
else if (time2 == 0)
{
time2 = 1;
num2 = nums[i];
}
else
{
--time1;
--time2;
}
}
time1 = 0, time2 = 0;
for (int i = 0; i < nums.size(); ++i)
{
if (num1 == nums[i]) ++time1;
else if (num2 == nums[i]) ++ time2;
}
if (time1 > nums.size() / 3) result.push_back(num1);
if (time2 > nums.size() / 3) result.push_back(num2);
return result;
}
};
// Python代码
class Solution:
# param {integer[]} nums
# return integer[]
def majorityElement(self, nums):
if not nums:
return []
num1, num2, time1, time2 = None, None, 0, 0
for num in nums:
if num1 == num:
time1 += 1
elif num2 == num:
time2 += 1
elif time1 == 0:
num1, time1 = num, 1
elif time2 == 0:
num2, time2 = num, 1
else:
time1, time2 = time1 - 1, time2 - 1
numSize = len(nums)
return [n for n in (num1, num2) if
n is not None and nums.count(n) > numSize / 3]
四. 小结