目录
多数元素
给定一个大小为 n 的数组,找到其中的多数元素。 多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。
这个问题我们可以用多种方法来解决它,这里列举三个方法
多数元素即众数,明白这个道理就变得轻而易举解决这个问题.
一丶排序
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr = {2,2,2,1,1,1,2};
System.out.println(manyNums(arr));
}
private static int manyNums(int[] arr) {
Arrays.sort(arr);//使用Arrays这个类来进行排序
return arr[arr.length/2];//排序以后的中数就是众数
}
}
二丶投票法
可以拿我们现实生活中的事情来举例,例如一个班有60人,现在要选一个班长,有A和B俩名同学参与竞选,投赞成票的+1,投反对票的-1,假如他获得了31票,然后正负相加之后大于一半,那么他就当选了.
public class Exercise1124 {
public static void main(String[] args) {
int[] nums = {7,7,5,7,5,1,5,7,5,5,7,7,7,7,7,7};
int num = manyNumVote(nums);
System.out.println(num);
}
private static int manyNumVote(int[] nums) {
//记录赞成人数
int count = 0;
Integer candidate = null;
for (int i:nums) {
//count= 0 就要换候选人
if(count == 0){
candidate = i;
}
//不赞成
if(i != candidate){
count+=-1;
}else {
count+=1;
}
}
return candidate;
}
}
三丶分治法
将一个数组拆分成俩部分,众数至少存在于其中一个子区间。
原问题:在一个区间找到众数,
子问题:在左半区间找到左边的众数leftNum,在右半区间找到右边的众数rightNum.
public class Exercise1124 {
public static void main(String[] args) {
int[] nums = {7, 7, 5, 7, 5, 1 ,5, 7 ,5, 5, 7, 7 ,7, 7, 7, 7};
int num = manyNumRecursion(nums);
System.out.println(num);
}
private static int manyNumRecursion(int[] nums) {
return manyNumRecursionInternal(nums,0,nums.length-1);
}
private static int manyNumRecursionInternal(int[] nums, int left, int right) {
if(left ==right){
//区间只有一个元素
return nums[left];
}
int mid = (left + right)/2;
//左半区间众数
int leftNum = manyNumRecursionInternal(nums,left,mid);
//又半区间众数
int rightNum = manyNumRecursionInternal(nums,mid+1,right);
if(leftNum == rightNum){
return leftNum;
}
//需要知道leftNum和rightNum在区间中出现的次数,返回较大的那个
int leftCount = numCount(nums,leftNum);
int rightCount = numCount(nums,rightNum);
return leftCount > rightCount ? leftNum : rightNum;
}
private static int numCount(int[] nums, int value) {
int count = 0;
for (int i:nums) {
if(i == value){
count++;
}
}
return count;
}
}