本文参考自《剑指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. OpenCV入门(2)- Java第一个程序

    1.下载和安装OpenVC环境 从官方连接 https://opencv.org/releases.html 下载Windows的安装包 下载下来的就是一个压缩包,安装解压后,对Java开发有效的目录 ...

  2. Java EE 之Hibernate异常总结【1】org.hibernate.LazyInitializationException: could not initialize proxy - no Session

    字面意义就是不能被初始化. 简单理解就是因为,你使用了lazy=true,这样hibernate在从数据库中调数据的时候是不会把关联的对象查出来的,而是保存一个获取值得方法,在你使用getXXX()调 ...

  3. luogu P2325 [SCOI2005]王室联邦

    传送门 做法是dfs整棵树,当访问一个点\(x\)时,先访问儿子,若某个时刻子树大小\(\ge b\)时,就把那些点放在一个省里,省会记为\(x\),访问完儿子再把\(x\)加入栈.最后栈中剩余的没加 ...

  4. Django 2.0 学习(12):Django 模板语法

    Django 模板语法 一.模板 只要是在html里面有模板语法就不是html文件了,这样的文件就叫做模板. 二.模板语法 模板语法变量:{{ }} 在Django模板中遍历复杂数据结构的关键是句点字 ...

  5. oracle建包,函数demo

    create table BOOK ( BOOK_ID NUMBER(10), BOOK_NAME VARCHAR2(10) ); create or replace package chen_pac ...

  6. 恶意代码分析实战-x86反汇编速成班

    x86反汇编速成 x86体系结构 3种硬件构成: 中央处理器:负责执行代码 内存(RAM):负责存储所有的数据和代码 输入/输出系统(I/O):为硬盘.键盘.显示器等设备提供接口 内存 一个程序的内存 ...

  7. Kaggle Titanic补充篇

    1.关于年龄Age 除了利用平均数来填充,还可以利用正态分布得到一些随机数来填充,首先得到已知年龄的平均数mean和方差std,然后生成[ mean-std,  mean+std ]之间的随机数,然后 ...

  8. 【vim】按时间回退文本 :earlier 1m

    Vim 会记录文件的更改,你很容易可以回退到之前某个时间.该命令是相当直观的.比如: :earlier 1m 会把文件回退到 1 分钟以前的状态. 注意,你可以使用下面的命令进行相反的转换: :lat ...

  9. UML和模式应用5:细化阶段(1)--第1次迭代

    1.前言 从本文开始进入细化阶段,讨论迭代技术的基础,本次讨论将着重讨论第一次迭代,以POS机为例. 2. 第一次迭代处理的需求(以NextGen POS项目处理销售用例) 实现 处理销售 用例中基本 ...

  10. saltStack的event接口通过mysql数据库接收SaltStack批量管理日志

    event是一个本地的ZeroMQ PUB Interface,event是一个开放的系统,用于发送信息通知salt或其他的操作系统.每个event都有一个标签.事件标签允许快速制定过滤事件.除了标签 ...