题干:
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。你可以假设数组是非空的,并且给定的数组总是存在多数元素。
如果不考虑空间复杂度,可以直接通过map来做,比较简单;如果要考虑空间复杂度为O(1),则需要使用Boyer-Moore 投票算法,具体代码及解析如下。
package likou;
/*
* 多数元素
* 题干:
* 给定一个大小为 n 的数组,找到其中的多数元素;
* 多数元素是指在数组中出现次数 大于n/2的下界
* 你可以假设数组是非空的,并且给定的数组总是存在多数元素
*/
public class Demo169 {
/*
* 解题思路一:定义一个hashMap,key为值,value为出现的次数,遍历即可找到多数元素
* 但这种思路的空间复杂度为O(n)
* 解题思路二:利用摩尔投票算法进行求解
* 定义一个多数元素为p,定义次数count,默认均为0
* 对nums数组进行遍历,当遇到相同的数据时,则count加1,否则count-1
* 当count等于0时,则将p和nums[i]交换
* 这里有点难以理解的就是为什么当count等于0时,将p和nums[i]交换就能计算出多数元素?
* 假设nums数组的多数元素为m,从nums[0]开始遍历,p = nums[0],当遍历到i时,count=0
* 最不理想的情况下,左边从0到i遍历过程中,m和p(nums[0])的个数相等
* 一般应该是nums[0]的个数要大于p
* 则在剩下的nums[i,nums.length-1]个元素过程中,m还是要占多数,不然不满足题干说明
* 在在nums[i,nums.length-1]集合中,只要m是多数,依然返回m
* 这样的算法空间复杂度为O(1)
*/
public int majorityElement(int[] nums) {
int p = nums[0];
int count = 1;
int length = nums.length;
for(int i=1;i<length;i++) {
if(count == 0) {
p = nums[i];
}
if(p == nums[i]) {
count++;
}else {
count--;
}
}
return p;
}
public static void main(String args[]) {
Demo169 demo = new Demo169();
int[] nums = {3,2,3};
System.out.println(demo.majorityElement(nums));
}
}