本文参考自《剑指offer》一书,代码采用Java语言。

更多:《剑指Offer》Java实现合集  

题目 

  数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1, 2, 3, 2, 2, 2, 5, 4, 2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。

思路

  思路一:数字次数超过一半,则说明:排序之后数组中间的数字一定就是所求的数字。

  利用partition()函数获得某一随机数字,其余数字按大小排在该数字的左右。若该数字下标刚好为n/2,则该数字即为所求数字;若小于n/2,则在右边部分继续查找;反之,左边部分查找。

  思路二:数字次数超过一半,则说明:该数字出现的次数比其他数字之和还多

  遍历数组过程中保存两个值:一个是数组中某一数字,另一个是次数。遍历到下一个数字时,若与保存数字相同,则次数加1,反之减1。若次数=0,则保存下一个数字,次数重新设置为1。由于要找的数字出现的次数比其他数字之和还多,那么要找的数字肯定是最后一次把次数设置为1的数字。

  也可以这样理解(来源:牛客网 cm问前程):

  采用阵地攻守的思想:
  第一个数字作为第一个士兵,守阵地;count = 1;
  遇到相同元素,count++;
  遇到不相同元素,即为敌人,同归于尽,count--;当遇到count为0的情况,又以新的i值作为守阵地的士兵,继续下去,到最后还留在阵地上的士兵,有可能是主元素。
  再加一次循环,记录这个士兵的个数看是否大于数组一般即可。

测试算例 

  1.功能测试(存在或者不存在超过数组长度一半的数字)

  2.特殊测试(null、1个数字)

Java代码

//题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例
//如输入一个长度为9的数组{1, 2, 3, 2, 2, 2, 5, 4, 2}。由于数字2在数组中
//出现了5次,超过数组长度的一半,因此输出2。 public class MoreThanHalfNumber {
boolean isInputInvalid = true; //方法一:partition方法
public int MoreThanHalfNum_Solution(int [] array) {
if(array==null ||array.length<=0)
return 0;
int low=0;
int high=array.length-1;
int index=partition(array,low,high);
while(index!=array.length>>1){
if(index<array.length>>1){
low=index+1;
index=partition(array,low,high);
}else{
high=index-1;
index=partition(array,low,high);
}
}
//判断次数是否超过一半
int num=array[index];
int times=0;
for(int i=0;i<array.length;i++){
if(array[i]==num){
times++;
}
}
if(times*2>array.length){
isInputInvalid=false;
return num;
}
return 0;
} private int partition(int[] array,int low ,int high){
int pivotKey=array[low];
while(low<high){
while(low<high && array[high]>=pivotKey)
high--;
int temp=array[low];
array[low]=array[high];
array[high]=temp;
while(low<high && array[low]<=pivotKey)
low++;
temp=array[low];
array[low]=array[high];
array[high]=temp;
}
return low;
} //方法二
public int MoreThanHalfNum_Solution2(int [] array) {
if(array==null || array.length<=0)
return 0;
int num=array[0];
int count=1;
for(int i=1;i<array.length;i++){
if(count==0) {
num=array[i];
count++;
}
else if(array[i]==num)
count++;
else
count--;
}
if(count>0){
int times=0;
for(int i=0;i<array.length;i++){
if(array[i]==num){
times++;
}
}
if(times*2>array.length){
isInputInvalid=false;
return num;
}
}
return 0;
}
}

  

收获

  1.length/2 用 length>>1 来代替,具有更高的效率;

  2.本题中,找到了所求数字,别忘记判断该数字的次数是否超过一半

  3.题目所要求的返回值为int,所以如果数组不满足要求时,无法通过返回值来告知是否出错,所以这道题设置了一个全局变量来进行判断。调用该方法时,需要记得对全局变量进行检查。

  4.方法一中,采用了partition()函数,该函数会改变修改的数组,因此在面试的时候,需要和面试官讨论是否可以修改数组。

  5.两种方法的时间复杂度均为O(n)。

更多:《剑指Offer》Java实现合集  

  

【Java】 剑指offer(39) 数组中出现次数超过一半的数字的更多相关文章

  1. 剑指 Offer 39. 数组中出现次数超过一半的数字 + 摩尔投票法

    剑指 Offer 39. 数组中出现次数超过一半的数字 Offer_39 题目描述 方法一:使用map存储数字出现的次数 public class Offer_39 { public int majo ...

  2. 剑指 Offer 39. 数组中出现次数超过一半的数字

    剑指 Offer 39. 数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字. 你可以假设数组是非空的,并且给定的数组总是存在多数元素. 示例 1: 输入: [ ...

  3. 力扣 - 剑指 Offer 39. 数组中出现次数超过一半的数字

    题目 剑指 Offer 39. 数组中出现次数超过一半的数字 思路1(排序) 因为题目说一定会存在超过数组长度一半的一个数字,所以我们将数组排序后,位于length/2位置的一定是众数 代码 clas ...

  4. 每日一题 - 剑指 Offer 39. 数组中出现次数超过一半的数字

    题目信息 时间: 2019-06-29 题目链接:Leetcode tag: 数组 哈希表 难易程度:简单 题目描述: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字. 假设数组是非空的 ...

  5. 剑指Offer:数组中出现次数超过一半的数字【39】

    剑指Offer:数组中出现次数超过一半的数字[39] 题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如,输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于这 ...

  6. 【剑指Offer】数组中出现次数超过一半的数字 解题报告(Python)

    [剑指Offer]数组中出现次数超过一半的数字 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-inter ...

  7. Go语言实现:【剑指offer】数组中出现次数超过一半的数字

    该题目来源于牛客网<剑指offer>专题. 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组 ...

  8. 剑指OFFER之数组中出现次数超过一半的数字(九度OJ1370)

    题目描述: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2 ...

  9. 剑指Offer 28. 数组中出现次数超过一半的数字 (数组)

    题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...

随机推荐

  1. 让 IE9 以下的浏览器支持 Media Queries

    1. 如何让 IE9 以下的浏览器支持 css3 的media query 需要用到的 min-width/max-width 属性 css3 的媒体查询 IE 浏览器的支持程度是从 IE9开始支持, ...

  2. Handler实现与机制 && Blocking Queue && IdleHandler使用

    http://blog.csdn.net/boyupeng/article/details/46685343 IdleHandler处理消息的源码 final Message next() { ... ...

  3. 使用layer 弹出对话框 子父页面相互参数传递 父页面获取子页面参数实例

    一.先看效果: 1.点击三个点的图标弹出了子页面: 2.子页面调用父页面方法,图一调用父页面方法,图二得到父页面var变量.           3.选择之后,关闭弹框,父页面得到子页面单选框选择的v ...

  4. typedef 用法总结

    原文转自:http://www.cnblogs.com/ggjucheng/archive/2011/12/27/2303238.html 引言 typedef 声明,简称 typedef,为现有类型 ...

  5. ubuntu 禁用自带的nouveau显卡驱动,安装NVIDIA显卡驱动

    下载显卡驱动 进入Nvidia的官网,找到对应GTX 750显卡的Linux 64-bit 的驱动程序,然后下载 当点击下载链接后,发现浏览器一直在加载那个*.run文件,很久都加载不完.这时将浏览器 ...

  6. Dubbo——基于Zookeeper服务框架搭建及案例演示

    一.了解SOA微服务架构 在大规模服务化之前,应用可能只是通过RMI或Hessian等工具,简单的暴露和引用远程服务,通过配置服务的URL地址进行调用,通过F5等硬件进行负载均衡. (1) 当服务越来 ...

  7. ReLu、LeakyRelu、PReLu(转载)

    转载链接:http://blog.csdn.net/cham_3/article/details/56049205

  8. linux内核中链表代码分析---list.h头文件分析(一)【转】

    转自:http://blog.chinaunix.net/uid-30254565-id-5637596.html linux内核中链表代码分析---list.h头文件分析(一) 16年2月27日17 ...

  9. 深入分析Linux自旋锁【转】

    转自:http://blog.chinaunix.net/uid-20543672-id-3252604.html 前言: 在复习休眠的过程中,我想验证自旋锁中不可休眠,所以编写了一个在自旋锁中休眠的 ...

  10. manjaro 的配置

    一.更新源的配置: 1).自动方法: 在 终端 执行下面的命令从官方的源列表中对中国源进行测速和设置 sudo pacman-mirrors -c China 2).手动方法 自动方法(上面的方法1, ...