题目内容:给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例1:
输入:[3,2,3]
输出:3
示例2:
输入:[2,2,1,1,1,2,2]
输出:2
第一种方法:排序法
将数组排序变成有序数组,众数一定出现在中间位置,因为众数的个数大于数组长度的一半。
代码如下:
public class MoreNum {
public static void main(String[] args) {
int[] arr={1,2,3,4,5,5,5,5,5,6};
System.out.println(moreNum(arr));
}
public static int moreNum(int[] arr){
Arrays.sort(arr);
return arr[arr.length/2];
}
}
第二种方法:分治法
将一个数组拆分成两部分,众数一定至少存在在一个子区间,然后在左半区间找到左边的众数left,在右半区间找到右边的众数right,如果left等于right,则众数就为left(或right),如果left不等于right,将left和right在原数组中计算出现次数,最后出现次数较多的那个就是最终结果。
代码如下:
public class MoreNum {
public static void main(String[] args) {
int[] arr={1,2,3,2,2,2,4};
System.out.println(manyNumRec(arr));
}
public static int manyNumRec(int[] arr){
return manyNumRecInter(arr,0,arr.length-1);
}
//传入一个数组以及该数组的左右区间,就可以找到该区间的众数
public static int manyNumRecInter(int[] arr,int left,int right){
if(left==right){
//区间只有一个元素
return arr[left];
}
int mid=(left+right)/2;
int leftNum=manyNumRecInter(arr,left,mid); //左半区间众数
int rightNum=manyNumRecInter(arr,mid+1,right); //右半区间众数
if(leftNum==rightNum){
return leftNum;
}
//需要知道leftNum和rightNum在区间中出现的次数,返回较大的那一个
int leftCount=numCount(arr,leftNum);
int rightCount=numCount(arr,rightNum);
return leftCount>rightCount?leftNum:rightNum;
}
public static int numCount(int[] arr,int value){
int count=0;
for (int i:
arr) {
if(i==value){
count++;
}
}
return count;
}
}
第三种方法:投票法
赞成投1
不赞成投-1
当count=0时需要重新选举候选人
代码如下:
public class MoreNum {
public static void main(String[] args) {
int[] arr={1,2,3,3,3,3,4,5,6,3};
System.out.println(manyNumVote(arr));
}
public static int manyNumVote(int[] arr){
int count=0;
Integer candidate=null;
for (int i:
arr) {
if(count==0){
candidate=i;
}
if(i!=candidate){
count+=-1;
}else{
count+=1;
}
}
return candidate;
}
}
分析如下: