题目及测试
package pid169;
/*求众数
给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在众数。
示例 1:
输入: [3,2,3]
输出: 3
示例 2:
输入: [2,2,1,1,1,2,2]
输出: 2
*/
public class main {
public static void main(String[] args) {
int[][] testTable = {{3,2,3},{2,2,1,1,1,2,2},{1,2,1}};
for (int[] ito : testTable) {
test(ito);
}
}
private static void test(int[] ito) {
Solution solution = new Solution();
int rtn;
long begin = System.currentTimeMillis();
for (int i = 0; i < ito.length; i++) {
System.out.print(ito[i]+" ");
}
System.out.println();
//开始时打印数组
rtn = solution.majorityElement(ito);//执行程序
long end = System.currentTimeMillis();
//System.out.println(ito + ": rtn=" + rtn);
System.out.println(": rtn=" +rtn);
System.out.println();
System.out.println("耗时:" + (end - begin) + "ms");
System.out.println("-------------------");
}
}
解法1(成功,27ms,很慢)
用hashmap装入key为数字,value为数字出现的个数,当加入的value大于mid时返回now
时间o(n) 空间o(n)
package pid169;
import java.util.HashMap;
public class Solution {
public int majorityElement(int[] nums) {
int length=nums.length;
int mid=length/2;
HashMap<Integer, Integer> map=new HashMap<>();
for(int i=0;i<length;i++){
int now=nums[i];
Integer nowNum;
if(map.containsKey(now)){
nowNum=map.get(now);
nowNum++;
}
else{
nowNum=1;
}
if(nowNum>mid){
return now;
}
map.put(now, nowNum);
}
return 0;
}
}
解法3(成功,2ms。极快)
摩尔投票算法
假设有这样一个场景:票选村长,每人可投一票,我们将候选村长从1开始编号,村民们在票上写上候选村长的编号即可完成投票。那么最后统计的票可形成一个整型数组。那么谁是村长呢?票数过半的那个人。
摩尔投票算法可以快速的计算出一个数组中出现次数过半的数即大多数(majority),算法核心思想是同加,异减。我们举个例子。
假设数组是:[1,2,1,1,2,1]。算法步骤如下:
1。当前大多数是1,得分置1
2。与当前大多数不同,得分 - 1,得分为0,当前大多数 = 1
1。与当前大多数不同,得分为0,所以设置当前大多数 1 -> 1,得分置1
1。与当前大多数相同,得分 + 1,得分为2,当前大多数 = 1
2。与当前大多数不同,得分 - 1 ,得分为1,当前大多数 = 1
1。与当前大多数相同,得分 + 1,得分为2,当前大多数 = 1
这意味着1是这个数组中出现次数过半的数。
可以感受得到,算法会保存一个当前大多数,和得分,当遇到一个数不是当前大多数时,得分会减一,当减到0时,大多数会发生改变,并且重置得分为1。
public int majorityElement(int[] nums) {
int length=nums.length;
if(length==0){
return 0;
}
if(length==1){
return nums[0];
}
int num=nums[0];
int counts=1;
for(int i=1;i<length;i++){
int now=nums[i];
// 已经冲掉了,新的进入
if(counts==0){
num=now;
counts=1;
continue;
}
if(now==num){
// 是同一个数字
counts++;
continue;
}else{
// 不是同一个数字
counts--;
continue;
}
}
return num;
}