1 题目:
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
2.思路:
方法一:排序的方法
先给数组排序,那么有超过数组长度一半的众数一定在中间也有。
时间复杂度:O(nlongn)
空间复杂度:O(1)
import java.util.Arrays; public class Solution { public int MoreThanHalfNum_Solution(int [] array) { Arrays.sort(array);//先给数组排序 int count=0; int half=array.length/2;//超过一半的众数一定在中间也有 for (int i=0;i<array.length;i++)//遍历 { if (array[i]==array[half]) count++; } if (count>half)//大于一般,满足条件 return array[half]; else return 0; } }
方法二:哈希法
采用HashMap记录每个值出现的次数
时间复杂度:O(n)
空间复杂度:O(n)
import java.util.HashMap;//引入HashMap类 public class Solution { public int MoreThanHalfNum_Solution(int [] array) { HashMap<Integer,Integer>hashMap=new HashMap<>();//此映射所维护的键的类型为整型,所映射值的类型为整型 for(int i=0;i<array.length;i++){//遍历 if(hashMap.containsKey(array[i])){//是否存在 hashMap.put(array[i],hashMap.get(array[i])+1);//映射值加1,记录重复的次数 }else{ hashMap.put(array[i],1);//第一次见到 } } for(int j=0;j<array.length;j++){//遍历 if(hashMap.get(array[j])>array.length/2){//是否出现的次数大于数组的一半 return array[j]; } } return 0; } }
方法三:摩尔投票法
遍历数组过程中保存两个值:一个是数组中某一数字,另一个是次数。遍历到下一个数字时,若与保存数字相同,则次数加1,反之减1。若次数=0,则保存下一个数字,次数重新设置为1。由于要找的数字出现的次数比其他数字之和还多,那么要找的数字肯定是最后一次把次数设置为1的数字。(当一个数的出现次数比其他数出现次数的总和还多时,说明这个值是符合条件的)
友情提示:当一个数最终的count>0,并不意味着这个数就符合要求了,比如在数组{1,2,3,4,5,6,7,7,7,8,9,10,10}中,运行完for循环后,最终会记录数字10,并且count为2。这一操作只是尽可能的在找一个出现次数较多的数。因此还需要进行一轮判断if。在第二轮过程中,count才是计数,判断数组中的数是否等于这个找出来的数(因为在不满足的条件的情况下,找出来的这个数只是出现次数较多,而非最多),如果有一半以上等于这个数,就找到,否则,不存在。
public class Solution { public int MoreThanHalfNum_Solution(int [] array) { int res=array[0];//res记录当前数字类型 int count=0;//count记录当前数字相较于其他数字的次数 for(int i=0;i<array.length;i++){ if(array[i]==res){//同一阵营+1 ++count; }else{//不同阵营-1 --count; } if(count==0){//消灭,开启新的阵营 res=array[i]; count=1; } } count=0; for(int j=0;j<array.length;j++){//再查询下淘汰出来的数字出现的次数 if(res==array[j]){ ++count; } } if(count>array.length/2){//是否真的大于一半 return res; } return 0; } }