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.
Example 1:
Input: [3,2,3]
Output: 3
Example 2:
Input: [2,2,1,1,1,2,2]
Output: 2
首先将数组均分成两半,分别找出每一半的主元素。如果两个主元素相等,则直接返回1个;否则遍历完整序列,找到最后赢家:返回出现次数多于一半的那个主元素。
(在某一侧无法分出胜负?没关系,在上一层继续比较,终究会找到最后赢家,因为主元素只有一个。例如[2,2,1,1,1,2,2] 在[2,2,1,1]无法找出部分的主元素,那么随意返回一个,在另一侧[1,2,2]总会找到赢家)
边界条件:序列只有一个元素时,直接返回该元素。
T(n) = 2T(n/2)+O(n)
时间复杂度:O(nlgn)
class Solution {
//这个方法用来在一定范围内计数
private int countInRange(int[] nums, int num, int lo, int hi) {
int count = 0;
for (int i = lo; i <= hi; i++) {
if (nums[i] == num) {
count++;
}
}
return count;
}
private int majorityElementRec(int[] nums, int lo, int hi) {
// 边界条件
if (lo == hi) {
return nums[lo];
}
// 把数组分为两半进行递归
int mid = (hi-lo)/2 + lo;
int left = majorityElementRec(nums, lo, mid);
int right = majorityElementRec(nums, mid+1, hi);
// 如果两边主元素相同,返回之
if (left == right) {
return left;
}
// 否则,遍历数组找到真正的主元素
int leftCount = countInRange(nums, left, lo, hi);
int rightCount = countInRange(nums, right, lo, hi);
return leftCount > rightCount ? left : right;
}
public int majorityElement(int[] nums) {
return majorityElementRec(nums, 0, nums.length-1);
}
}
Runtime: 3 ms, faster than 99.43% of Java online submissions for Majority Element.
Memory Usage: 39.2 MB, less than 93.85% of Java online submissions for Majority Element.
由题目的性质可以发现,将数组排序后,位于中间的数字一定是主元素。那么使用快排即可。
平均时间复杂度:O(nlgn)
class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length/2];
}
}
Runtime: 3 ms, faster than 99.43% of Java online submissions for Majority Element.
Memory Usage: 41.2 MB, less than 28.89% of Java online submissions for Majority Element.
这是在solution中翻到的答案,十分巧妙。
根据题目的性质,我们知道所要找的主元素的数量比其他数都多,因此将数字可以分成两类,一类是主元素,另一类是“余数”。用一个标记candidate记录某个元素出现的次数,这个元素称为候选者。如果后面的元素和它相同就投票+1,有一个元素和他不相同就投票-1,当candidate小于等于0时,重新记录新的元素。 当遍历完成后,只有真正的主元素会被留下,而其它的余数在过程中总会吃到反对票而失去候选者的资格。
时间复杂度:O(n) 空间复杂度:O(1) 简单粗暴
class Solution {
public int majorityElement(int[] nums) {
int count = 0;
Integer candidate = null;
for (int num : nums) {
if (count == 0) {
candidate = num;
}
count += (num == candidate) ? 1 : -1;
}
return candidate;
}
}
Runtime: 4 ms, faster than 71.04% of Java online submissions for Majority Element.
Memory Usage: 41 MB, less than 32.49% of Java online submissions for Majority Element.