题目:

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。

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

思路:

1、方法1:

先排序,然后找中位数;

时间复杂度O(nlogn)

2、方法2:

基于Partition函数的O(n)算法,即寻找第k(k=n/2)大的数;

平均时间复杂度:O(n)

3、方法3:

根据数组特点,采用Moore-Vote方法。

由于该数字的出现次数比所有其他数字出现次数的和还要多,因此可以考虑在遍历数组时保存两个值:一个是数组中的一个数字,一个是次数,。当遍历到下一个数字时,如果下一个数字与之前保存的数字相同,则次数加1,如果不同,则次数减1,如果次数为0,则需要保存下一个数字,并把次数设定为1。由于我们要找的数字出现的次数比其他所有数字的出现次数之和还要大,则要找的数字肯定是组后一次把次数设为1时对应的数字。

时间复杂度为O(n),空间复杂度为O(1)。

代码:

方法2:

#include <iostream>

using namespace std;

bool g_bInputInvalid=false;

bool CheckInvalidArray(int* numbers,int length){
if(numbers==NULL || length<=0)
g_bInputInvalid=true;
return g_bInputInvalid;
} bool CheckMoreThanHalf(int* numbers,int length,int number){
int times=0;
for(int i=0;i<length;i++){
if(numbers[i]==number)
times++;
}
bool isMoreThanHalf=true;
if(times*2<=length){
g_bInputInvalid=true;
isMoreThanHalf=false;
}
return isMoreThanHalf;
} int Partition(int* numbers,int start,int end){
int key=numbers[start];
int i=start;
int j=end;
while(i<j){
while(i<j && numbers[j]>=key)
--j;
if(i<j) numbers[i++]=numbers[j]; while(i<j && numbers[i]<=key)
++i;
if(i<j) numbers[j--]=numbers[i];
}
numbers[i]=key;
return i;
} int MoreThanHalfNum(int* numbers,int length){
if(CheckInvalidArray(numbers,length))
return 0;
int mid=length>>1;
int start=0;
int end=length-1;
int index=Partition(numbers,start,end);
while(index!=mid){
if(index>mid){
end=index-1;
index=Partition(numbers,start,end);
}
else{
start=index+1;
index=Partition(numbers,start,end);
}
}
int result=numbers[index];
if(!CheckMoreThanHalf(numbers,length,result))
result=0;
return result;
} int main()
{
int A[]={3,1,3,2,4,3,3,5,3,7,3};
int length=sizeof(A)/sizeof(A[0]);
cout << MoreThanHalfNum(A,length) << endl;
return 0;
}

方法3:

#include <iostream>

using namespace std;

bool g_bInputInvalid=false;

bool CheckInvalidArray(int* numbers,int length){
if(numbers==NULL || length<=0)
g_bInputInvalid=true;
return g_bInputInvalid;
} bool CheckMoreThanHalf(int* numbers,int length,int number){
int times=0;
for(int i=0;i<length;i++){
if(numbers[i]==number)
times++;
}
bool isMoreThanHalf=true;
if(times*2<=length){
g_bInputInvalid=true;
isMoreThanHalf=false;
}
return isMoreThanHalf;
} int MoreThanHalfNum_1(int* numbers,int length){
if(CheckInvalidArray(numbers,length))
return 0; int result=numbers[0];
int times=1;
for(int i=1;i<length;i++){
if(times==0){
result=numbers[i];
times=1;
}
if(result==numbers[i])
times++;
else
times--;
}
if(!CheckMoreThanHalf(numbers,length,result))
result=0;
return result;
} int main()
{
int A[]={3,1,3,2,4,3,3,5,3,7,3};
int length=sizeof(A)/sizeof(A[0]);
cout << MoreThanHalfNum_1(A,length) << endl;
return 0;
}

在线测试OJ:

http://www.nowcoder.com/books/coding-interviews/e8a1b01a2df14cb2b228b30ee6a92163?rp=2

AC代码:

方法1:

class Solution {
public:
int Partition(vector<int> &numbers,int start,int end){
int key=numbers[start];
int i=start;
int j=end;
while(i<j){
while(i<j && numbers[j]>=key)
--j;
if(i<j) numbers[i++]=numbers[j]; while(i<j && numbers[i]<=key)
++i;
if(i<j) numbers[j--]=numbers[i];
}
numbers[i]=key;
return i;
} int MoreThanHalfNum_Solution(vector<int> numbers) {
int length=numbers.size();
if(length<=0)
return 0;
int mid=length>>1;
int start=0;
int end=length-1;
int index=Partition(numbers,start,end);
while(index!=mid){
if(index>mid){
end=index-1;
index=Partition(numbers,start,end);
}
else{
start=index+1;
index=Partition(numbers,start,end);
}
} int result=numbers[index];
int times=0;
for(int i=0;i<length;i++){
if(numbers[i]==result)
times++;
}
if(times*2<=length)
result=0; return result;
}
};

方法2:

class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
int length=numbers.size();
if(length<=0)
return 0;
int result=numbers[0];
int times=1;
for(int i=1;i<length;i++){
if(times==0){
result=numbers[i];
times=1;
}
if(result==numbers[i])
times++;
else
times--;
} int t=0;
for(int i=0;i<length;i++){
if(numbers[i]==result)
t++;
}
if(t*2<=length)
result=0; return result;
}
};

(剑指Offer)面试题29:数组中出现次数超过一半的数字的更多相关文章

  1. 剑指Offer:面试题29——数组中出现次数超过一半的数字(java实现)

    PS:在前几天的面试中,被问到了这个题.然而当时只能用最低效的方法来解. 问题描述: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2, ...

  2. 剑指Offer - 九度1370 - 数组中出现次数超过一半的数字

    剑指Offer - 九度1370 - 数组中出现次数超过一半的数字2013-11-23 03:55 题目描述: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组 ...

  3. 【剑指Offer】28、数组中出现次数超过一半的数字

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

  4. 《剑指offer》39题—数组中出现次数超过一半的数字

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

  5. 剑指Offer:找出数组中出现次数超过一半的元素

    题目:找出数组中出现次数超过一半的元素 解法:每次删除数组中两个不同的元素,删除后,要查找的那个元素的个数仍然超过删除后的元素总数的一半 #include <stdio.h> int ha ...

  6. 剑指offer(28)数组中出现次数超过一半的数

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

  7. 【Offer】[39] 【数组中出现次数超过一半的数字】

    题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如,输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数 ...

  8. 《剑指offer》面试题39. 数组中出现次数超过一半的数字

    问题描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字. 你可以假设数组是非空的,并且给定的数组总是存在多数元素. 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, ...

  9. 剑指offer 面试题56. 数组中只出现一次的两个数字

    题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 方法1:用set记录出现过的数字 class Solution { public: void F ...

  10. 【剑指offer】找出数组中任意一个重复的数字,C++实现

    原创博文,转载请注明出处! # 题目 # 思路 对于长度为n的数组,范围为0~n-1的数字而言,如果不粗在重复数字,则排序后数组元素和数组角标相同.如果存在重复数字,则在排序的过程中会出现不同下标对应 ...

随机推荐

  1. Android 多进程编程 15问15答!

    ps:阅读本文 需要对android 多进程编程有一定了解. 1.Android中总共有几种方式进行IPC? 答:一共有两种,一种是binder 还有一种是socket.Binder 大家用的比较多. ...

  2. IOS公司开发者账号申请详细教程

    谈到苹果开发者账号,我们需要区分一下个人账号.公司账号和企业账号这三种,还有一种是教育账号,这个就不多说了. 个人账号:个人申请用于开发苹果app所使用的账号,仅限于个人使用,申请比较容易,$99. ...

  3. cocos2dx+lua中cc.EventListenerMouse:create()的bug

    今天在调试项目的时候用到了鼠标事件的监听 在创建事件监听器的时候出了问题 cc.EventListenerMouse:create() 这句返回值为nil 原来这是cocos2dx引擎的一个bug,t ...

  4. HDU5805 NanoApe Loves Sequence (BestCoder Round #86 B)前后缀预处理

    分析:维护空隙的差,然后预处理前缀最大,后缀最大,扫一遍 #include <cstdio> #include <cstring> #include <cmath> ...

  5. 关于python中字典的一些总结

    1. 获取字典中的值,但是无异常 当在字典中取值的时候,可以使用如下两种方式: >>> d = {'name':'kel'} >>> d {'name': 'kel ...

  6. Quartz与Spring集成

    关于Quartz的基本知识,这里就不再多说,可以参考Quartz的example. 这里主要要说的是,个人在Quartz和Spring集成的过程中,遇到的问题和个人理解. 首先来说说个人的理解: 1. ...

  7. activity切换时的overridePendingTransition动画效

      注意,切换方法overridePendingTransition只能在startActivity和finish方法之后调用.第一个参数为第一个Activity离开时的动画,第二参数为所进入的Act ...

  8. SVN的搭建和使用总结

    Subversion是优秀的版本控制工具,其具体的的优点和详细介绍就不多做介绍,主要说一下SVN的服务端搭建.客户端安装.使用及出现的问题的解决办法. 首先来下载和搭建SVN服务器. 现在Subver ...

  9. Shell script之if...then

    1 Variable in shell  If you want to print variable, then use echo command. In front of the variable ...

  10. 为operamasks增加HTML扩展方式的组件调用

    #为operamasks增加HTML扩展方式的组件调用 ##背景 之前的[博文](http://www.cnblogs.com/p2227/p/3540858.html)中有提及到,发现easyui中 ...