Description
Given an array nums of size n, return the majority element.
The majority element is the element that appears more than ⌊n / 2⌋ times. You may assume that the majority element always exists in the array.
Examples
Example 1:
Input: nums = [3,2,3]
Output: 3
Example 2:
Input: nums = [2,2,1,1,1,2,2]
Output: 2
Constraints:
n == nums.length
1 <= n <= 5 * 1 0 4 10^4 104
− 1 0 9 -10^9 −109 <= nums[i] <= 1 0 9 10^9 109
Follow-up: Could you solve the problem in linear time and in O(1) space?
思路
虽然这题只是easy,但还是有几种不同的方式来处理。以下所有处理方式都基于 “majority number的数量超过数组数量的一半”
排序
最开始也是最简单的方法,就是对数组进行排序,由于majority数量超过数组数量的一半,所以直接查找排序后的中点即可。
MAP
通过map存储每个数字的数量,一旦这个数量超过一半,就退出循环,认为这个数是majority number
二分查找
我们对一个序列,递归的搜索他左半边和右半边的majority number,对以下两重情况进行分别处理
- majority左 = = = majority右 → majority确定
- majority左 ≠ \neq = majority右 → 分别计算majority左和majority右在序列中的数量,选择数量多的作为该序列的majority
Boyer-Moore Voting
这个solution里面看到的,他用了一个很tricky的方法,既然majority的数量一定是 > half 的,那我们假设[0]为majority,count的数量为1,然后依次对序列中的每个单词进行判断
- count == 0? 重置当前num为majority
- count != 0?
- 当前num == majority → count++
- 当前num != majority → count–
到最后剩下的majority就是majority,取一种最极端的情况
- 前 n/2+1 都是majority,那到最后 count=1,majority=[0]
其他情况下,由于count(majority) > half,都会导致最后剩下的是majortiy
代码
排序
class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length / 2];
}
}
MAP
class Solution {
public int majorityElement(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
for (int num: nums){
int n = map.getOrDefault(num, 0);
if (n >= nums.length / 2)
return num;
map.put(num, n + 1);
}
return -1;
}
}
二分查找
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) {
// base case; the only element in an array of size 1 is the majority
// element.
if (lo == hi) {
return nums[lo];
}
// recurse on left and right halves of this slice.
int mid = (hi-lo)/2 + lo;
int left = majorityElementRec(nums, lo, mid);
int right = majorityElementRec(nums, mid+1, hi);
// if the two halves agree on the majority element, return it.
if (left == right) {
return left;
}
// otherwise, count each element and return the "winner".
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);
}
}
Boyer-Moore Voting
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;
}
}