题目:

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

例如输入一个长度为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. Heritrix源码分析(四) 各个类说明(转)

    Heritrix的类的确很繁琐,往往继承了一层又一层,最多的继承好像有7层.下面就一个包一个包的说明每个类的作用,由于里面Heritrix组件分明,很多组件没用到的同时该组件的类我也没怎么接触,所以这 ...

  2. Android studio gradle 打包 那些事

    总结了一下 目前觉得比较好用的gradle 和一些打包 经验.放在这里. 首先说下 渠道号 这个概念,我们经常会统计我们的api 访问来源 是来自于那个app store,这有利于 我们针对性的推广. ...

  3. Android Studio Check for Update

    Android Studio 当前版本1.0.1, 官网新版本1.1.0, 通过 Check for Update...升级, 提示 Connection failed. Please check y ...

  4. 设计模式-单键(Singleton)

    [摘要]   在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性.以及良好的效率. 如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例? 这应该 ...

  5. ANSI

    为了扩充ASCII编码,以用于显示本国的语言,不同的国家和地区制定了不同的编码标准,由此产生了GB2312.BIG5.JIS等各自的编码标准.这些使用两个字节来代表一个字符的各种汉字延伸编码方式被称为 ...

  6. JavaScript 性能优化 --By Google V8 Team Manager

    原文:https://developers.google.com/v8/?hl=zh-CN Be Prepared before writing code[9:35] Understand how V ...

  7. 使用最小堆来完成k路归并 6.5-8

    感谢:http://blog.csdn.net/mishifangxiangdefeng/article/details/7668486 声明:供自己学习之便而收集整理 题目:请给出一个时间为O(nl ...

  8. Hadoop-chd4.4.0安装

    Hadoop-cdh4下载地址: http://www.cloudera.com/content/cloudera-content/cloudera-docs/CDHTarballs/3.25.201 ...

  9. PHP 碎片

    1. $_SERVER['REMOTE_ADDR'] cannot be modified by the user or via HTTP so you CAN trust it. -- 用这个可以有 ...

  10. Educational Codeforces Round 5 A. Comparing Two Long Integers

    A. Comparing Two Long Integers time limit per test 2 seconds memory limit per test 256 megabytes inp ...