数组中出现次数超过一半的数字(java版)
2017-05-12 23:16
357 查看
【题目描述】数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
【解题思路1】
先来看一种最简单的解法,算法复杂度为O(n*log(n))
//1.对数组进行排序,然后遍历
//2.遍历过程中,记录当前元素的出现次数,若超过数组长度的一半,即返回该值
//3.若遍历到最后也没有发现符合条件的元素,按照题目要求,返回 0
【源码1】
a. sum用来记录当前值出现的次数。若出现当前值变化的情况,需要重置
b. 设置标志位flag,是针对遍历到最后并没有发现符合条件的值的情况。
【解题思路2】在 “思路1” 的基础上做一个小小的改进。
//1.对数组进行排序
//2.假设存在出现次数超过一半的数字target,则其位于中位数的位置上。此时,无论中位数为单个数值,还是为两个数值的平均数,都为该值。因为若数组长度为偶数,中位数取中间两个值的平均数,此时两个值应该是相同的,都等于最后要求的这个数字target。
//3.求得target后,对数组进行一次遍历,计算target出现的次数,若超过一半则返回该值。否则,不存在符合条件的值,返回0。
【源码2】
【解题思路3】最简单直观的考虑。分别计算每个元素出现的次数,取最大值与len/2做比较。时间复杂度为O(n)。
//1.使用hashmap
a. 使用迭代器iterator,加快遍历速度。
【解题思路4】该思路来自剑指offer的解法二,称为“打擂法”,也叫“守阵地思想”。若数组中有一个数字出现次数超过一半,则它出现的次数超过了其他所有数字出现次数的总和。算法复杂度为O(n)。
//1. 遍历数组,同时维护两个值:一个是数组中的一个元素e,另一个是次数count。
//2. 遍历过程中,若下一个元素和之前保存的e不相同,则次数count-1。若相同,则count+1。
//3. 若出现次数为零的情况,则e需要存储下一个数字,并把次数count=1。
//4. 若存在符合条件的元素,最后一次把次数置为1的数字即要找的目标值。否则,返回0。
//5. 验证最后维护的元素e,出现次数是否超过一半。
【源码4】
【解题思路5】该思路来自剑指offer第一种解法。该解法会改变原数组。
//1. 若有一个数字出现次数超过了一半,则排序之后位于数组中间的那个数字就是要求的值。
//2. 在随机快速排序算法中,先在数组中随机选一个数字,调整数组中数字的顺序。使得比选中的数字小的数位于其左边,比选中的数字大的数字位于其右边。
//3. 如果这个选中的数字的下标刚好是n/2,则这个数字就是数组的中位数。如果它的下标比n/2大,则中位数应该位于其左边,继续在左边查找。如果它的下标比n/2小,则中位数应位于其右边,继续在右边查找。
【源码5】
【解题思路1】
先来看一种最简单的解法,算法复杂度为O(n*log(n))
//1.对数组进行排序,然后遍历
//2.遍历过程中,记录当前元素的出现次数,若超过数组长度的一半,即返回该值
//3.若遍历到最后也没有发现符合条件的元素,按照题目要求,返回 0
【源码1】
import java.util.Arrays; public class Solution { public int MoreThanHalfNum_Solution(int [] array) { if(array.length == 0){ return 0; } Arrays.sort(array); boolean flag = false; int mNum=array[0], sum=0, temp=array[0], len=array.length/2; for(int a: array){ if(a == temp){ sum++; mNum = a; } if(sum > len ){ flag = true; break; } if(a != temp){ sum = 1; temp = a; } } if(flag == false){ mNum = 0; } return mNum; } }
a. sum用来记录当前值出现的次数。若出现当前值变化的情况,需要重置
sum=1, 注意此时sum为1,不为0。
b. 设置标志位flag,是针对遍历到最后并没有发现符合条件的值的情况。
【解题思路2】在 “思路1” 的基础上做一个小小的改进。
//1.对数组进行排序
//2.假设存在出现次数超过一半的数字target,则其位于中位数的位置上。此时,无论中位数为单个数值,还是为两个数值的平均数,都为该值。因为若数组长度为偶数,中位数取中间两个值的平均数,此时两个值应该是相同的,都等于最后要求的这个数字target。
//3.求得target后,对数组进行一次遍历,计算target出现的次数,若超过一半则返回该值。否则,不存在符合条件的值,返回0。
【源码2】
import java.util.Arrays; public class Solution { public int MoreThanHalfNum_Solution(int [] array) { Arrays.sort(array); int count=0, len=array.length; for(int i=0;i<len;i++){ if(array[i]==array[len/2]){ count++; } } if(count>len/2){ return array[len/2]; }else{ return 0; } } }
【解题思路3】最简单直观的考虑。分别计算每个元素出现的次数,取最大值与len/2做比较。时间复杂度为O(n)。
//1.使用hashmap
链接:https://www.nowcoder.com/questionTerminal/e8a1b01a2df14cb2b228b30ee6a92163 来源:牛客网 public class Solution { public int MoreThanHalfNum_Solution(int [] array) { HashMap<Integer,Integer> map = new HashMap<Integer,Integer>(); for(int i=0;i<array.length;i++){ if(!map.containsKey(array[i])){ map.put(array[i],1); }else{ int count = map.get(array[i]); map.put(array[i],++count); } } Iterator iter = map.entrySet().iterator(); while(iter.hasNext()){ Map.Entry entry = (Map.Entry)iter.next(); Integer key =(Integer)entry.getKey(); Integer val = (Integer)entry.getValue(); if(val>array.length/2){ return key; } } return 0; }
a. 使用迭代器iterator,加快遍历速度。
【解题思路4】该思路来自剑指offer的解法二,称为“打擂法”,也叫“守阵地思想”。若数组中有一个数字出现次数超过一半,则它出现的次数超过了其他所有数字出现次数的总和。算法复杂度为O(n)。
//1. 遍历数组,同时维护两个值:一个是数组中的一个元素e,另一个是次数count。
//2. 遍历过程中,若下一个元素和之前保存的e不相同,则次数count-1。若相同,则count+1。
//3. 若出现次数为零的情况,则e需要存储下一个数字,并把次数count=1。
//4. 若存在符合条件的元素,最后一次把次数置为1的数字即要找的目标值。否则,返回0。
//5. 验证最后维护的元素e,出现次数是否超过一半。
【源码4】
public class Solution { public int MoreThanHalfNum_Solution(int [] array) { int length=array.length; if(array==null||length<=0){ return 0; } int result=array[0]; int times=1; for(int i=1;i<length;i++){ if(times==0){ result=array[i]; times=1; }else{ if(array[i]==result){ times++; }else{ times--; } } } times=0; for(int i=0;i<length;i++){ if(result==array[i]){ times++; } } if(times*2<length){ result=0; } return result; } }
【解题思路5】该思路来自剑指offer第一种解法。该解法会改变原数组。
//1. 若有一个数字出现次数超过了一半,则排序之后位于数组中间的那个数字就是要求的值。
//2. 在随机快速排序算法中,先在数组中随机选一个数字,调整数组中数字的顺序。使得比选中的数字小的数位于其左边,比选中的数字大的数字位于其右边。
//3. 如果这个选中的数字的下标刚好是n/2,则这个数字就是数组的中位数。如果它的下标比n/2大,则中位数应该位于其左边,继续在左边查找。如果它的下标比n/2小,则中位数应位于其右边,继续在右边查找。
【源码5】
链接:https://www.nowcoder.com/questionTerminal/e8a1b01a2df14cb2b228b30ee6a92163 来源:牛客网 public class Solution { public int MoreThanHalfNum_Solution(int [] array) { if(array==null||array.length==0) return 0; int middle=array.length>>1; int start=0; int end=array.length-1; int index=Partition(array,start,end); while(index!=middle){ if(index>middle){ end=index-1; ndex=Partition(array,start,end); }else{ start=index+1; index=Partition(array,start,end); } } int result=array[middle]; if(!CheckMoreThanHalf(array,result)) result=0; return result; } public static boolean CheckMoreThanHalf(int array[],int number){ int times=0; for(int i=0;i<array.length;++i){ if(array[i]==number) times++; } boolean isMoreThanHalf=true; if(times*2<=array.length){ isMoreThanHalf=false; } return isMoreThanHalf; } public static int Partition(int array[],int start,int end){ int pivotkey=(int)start+(int)Math.random()*(end-start); while(start<end){ while(start<end&&array[end]>=array[pivotkey]) end--; int temp=array[start]; array[start]=array[end]; array[end]=temp; while(start<end&&array[start]<=array[pivotkey]) start++; temp=array[start]; array[start]=array[end]; array[end]=temp; } return start; } }
相关文章推荐
- 剑指Offer(java版):数组中出现次数超过一半的数字
- java之数组中出现次数超过一半的数字
- JAVA: 数组中出现次数超过一半的数字
- java 找到数组中出现次数超过数组长度一半的那个数字
- 数据结构与算法分析笔记与总结(java实现)--数组4:数组中出现次数超过一半的数字
- 数组中出现次数超过一半的数字 -java
- 《剑指offer》编程题java实现(十):数组中出现次数超过一半的数字
- 剑指offer:数组中出现次数超过一半的数字(java)
- 剑指Offer面试题29(java版):数组中出现次数超过一半的数字
- 数组中出现次数超过一半的数字(Java实现)
- 【剑指offer-Java版】29数组中出现次数超过一半的数字
- 剑指Offer面试题29(java版):数组中出现次数超过一半的数字
- 基于Java代码实现数字在数组中出现次数超过一半
- java实现找出数组中出现次数超过一半的数字
- java实现:数组中出现次数超过一半的数字
- 剑指Offer:面试题29——数组中出现次数超过一半的数字(java实现)
- 面试题29:找到数组中出现次数超过一半的数字(java)
- 剑指Offer面试题29:数组中出现次数超过一半的数字 Java实现
- 数组中有一个数字出现的次数超过了数组长度的一半,请找出这个数。java实现
- 数组中超过出现次数超过一半的数字