题目:

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

例如输入一个长度为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. SSH思路

    hibernate的配置写到spring的配置中,用spring管理和调用hibernate的工厂和session等.struts的话,通常有2中.一种是用spring中的一个工厂类代替struts的 ...

  2. 使用Jekyll搭建博客

    最近闲来无事,捣鼓了一下Git以及Github,尝试了一下基于Jekyll搭建个人博客的方法,现在把整个过程进行一个总结(部分内容转自互联网): <img src="http://up ...

  3. 【转】Eclipse编辑shell的插件(shellEd)

    原文网址:http://blog.sina.com.cn/s/blog_a42d507e01019mlp.html Eclipse官方网站:http://download.eclipse.org/ 1 ...

  4. Oracle RAC 服务器端连接负载均衡(Load Balance)

    Oracle RAC服务器端的负载均衡是根据RAC中各节点的连接负荷数情况,将新的连接请求分配到负荷最小的节点上去.当数据库处于运行时,RAC中各节点的PMON进程每3秒会将各自节点的连接负荷数更新到 ...

  5. unity, sprite atlas

    一, Sprite Packer 可以直接在unity里放碎图,只要将Texture Type选为Sprite(2D and UI),Sprite Mode选为Single,再把想打在一张大图里的碎图 ...

  6. hdu 5510 Bazinga (kmp+dfs剪枝) 2015ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学)

    废话: 这道题很是花了我一番功夫.首先,我不会kmp算法,还专门学了一下这个算法.其次,即使会用kmp,但是如果暴力枚举的话,还是毫无疑问会爆掉.因此在dfs的基础上加上两次剪枝解决了这道题. 题意: ...

  7. Masonry 固定宽度 等间距

    -(void)makeEqualDisViews:(NSArray *)views inView:(UIView *)containerView LRpadding:(CGFloat)LRpaddin ...

  8. selenium python (一) 开发环境搭建

    1.工具下载: python工具共包括三个:python.setuptools.pip ²  python:http://python.org/getit/     python开发环境: ²  se ...

  9. [转]Linux之od命令

    转自:http://os.51cto.com/art/200912/173136.htm 随着计算机飞速的发展,很多人开始学习Linux,怎样才能学好Linux,一定要学好Linux的命令.学习Lin ...

  10. Intent传输数据的补充

    发现用intent的putExtra()或者putExtras()传输的都是基本数据类型. 如果要传输自定义数据类型,就要用到其他方法,老罗介绍的大概有3种: 1.  静态变量 2.  全局变量 3. ...