给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
思路一:
自己的思路,估计也是最容易想到而且效率最低的。就是通过一个HashMap来存储每个key出现的次数。不过通过编写这个,我了解了Map的遍历方式。也就是通过遍历Map中的Entry来获取key和value。
- 时间复杂度:O(n)。
- 空间复杂度:O(n),因为使用哈希表。
class Solution {
public int majorityElement(int[] nums) {
HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
for(int i:nums){
if(map.containsKey(i)){
int tmp = map.get(i);
map.put(i,tmp+1);
}else{
map.put(i,1);
}
}
Iterator<Map.Entry<Integer,Integer>> it = map.entrySet().iterator();
while(it.hasNext()){
Map.Entry<Integer,Integer> entry = it.next();
if(entry.getValue()>nums.length/2){
return entry.getKey();
}
}
return 0;
}
}
思路二:
先对数组进行排序,那么在下标为n/2的值就是众数。
- 时间复杂度:O(nlogn)
- 空间复杂度:O(1)或者O(n)。如果可以原地就是O(1),还要新建一个数组就是O(n)。
class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length/2];
}
}
思路三:
分治法。每一个区间都会有一个众数,对于只有一个数字的区间,显然众数就是该数。将两个区间合并起来时,如果他们的众数相等,则该数依然为此大区间的众数,不等就要统计两个众数在这个区间内谁才是真的众数。(分治也就是先拆分成小的,再一个一个组合成大的)
- 时间/空间复杂度均为O(nlogn)。
class Solution {
public int majorityElement(int[] nums) {
return getMajority(nums,0,nums.length-1);
}
public int getMajority(int[] nums,int left,int right){
if(left==right) return nums[left];
int leftMajor = getMajority(nums,left,(left+right)/2);
int rightMajor = getMajority(nums,(left+right)/2+1,right);
if(leftMajor==rightMajor){
return leftMajor;
} else{
int leftNum = numberInRange(nums,left,right,leftMajor);
int rightNum = numberInRange(nums,left,right,rightMajor);
return leftNum>rightNum?leftMajor:rightMajor;
}
}
public int numberInRange(int[] nums,int left,int right,int num){
int res = 0;
for(int i=left;i<=right;i++){
if(nums[i]==num){
res++;
}
}
return res;
}
}
思路四:
Boyer-Moore 投票算法!!!
首先我们需要知道,众数的数量比其他数加起来还要多,所以可以采用这个方法:
设置一个数,命名为“候选众数”,为他设置一个计数器x。起初让它的值为数组的第一个数(x记为1),然后然后遍历,遇到一个候选众数就x++,遇到非候选众数就x–。如果x=0了,就废弃掉这个候选众数,选取下一个便利的数作为新的候选众数。一直到数组尾部,此时的候选众数,就是真正的众数。
原理是真正的众数足够多,可以抵消掉所有的非众数。
- 时间复杂度:O(n)
- 空间复杂度:O(1)
class Solution {
public int majorityElement(int[] nums) {
int tempMajor = nums[0];
int x = 1;
for(int i=1;i<nums.length;i++){
if(x==0) tempMajor = nums[i];
if(nums[i]==tempMajor){
x++;
}else{
x--;
}
}
return tempMajor;
}
}