题目描述:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
例如输入一个长度为 9 的数组{1,2,3,2,2,2,5,4,2}。
由于数字2在数组中出现了 5 次,超过数组长度的一半,因此输出2。
如果不存在则输出 0
解法一:简易解法,低效
题解:我们可以先对整个数组进行排序,当排好序以后,如果解存在,则需要的那个数一定就在中间的位置,因为它的个数已经超过了整个数组的一半。如果解不存在就按题意返回0
int MoreThanHalfNum_Solution(vector<int> numbers) {
//第一部分:判断代码的鲁棒性
if(numbers.empty()){
return 0;
}
// 第二部分:对数组进行排序,并取出中间的数字
sort(numbers.begin(),numbers.end());
int middle = numbers[numbers.size()/2];
// 第三部分:判断中间的数字出现的次数
int count = 0;
for(int i = 0;i<numbers.size();++i){
if(numbers[i] == middle){
++count;
}
}
// 第四部分:如果超过一半则返回中间的数字,否则返回0
if(count > numbers.size()/2){
return middle;
}else{
return 0;
}
}
代码框架:大致可以分为四个部分1.判断数组是否有;2取出排序后中间的数字;3.计算中间数字在整个数组出现的次数,4.最后判断次数是否大于整个数组长度的一半。
注意:由于用到了sort函数,所以它的时间复杂度肯定不会满足面试官的要求,那么就得要寻找更快速的解法。
解法二:高效遍历
这个和解法一有相似之处,都是先把最有可能满足题意要求的数字保存起来,然后在最后判断它是否满足要求,如果满足就返回它的值,如果不满足就返回0,但是它比解法一高效的地方在于没有排序,直接进行的遍历。
方法:我们在遍历数组的时候,保存两个值,一个是数组中的数字,另一个是次数,当遍历到下一个数字的时候,如果和上一次的数字一样则次数加1,如果不一样次数减一(相当于抵消了),如果次数为0了,那就保存下一个数字,并把次数设置为1,因为我们要找的数字如果存在最后一定是把次数设置为1的那个数。
int MoreThanHalfNum_Solution(vector<int> numbers) {
if(numbers.empty()){
return 0;
}
int temp = numbers[0];
int time = 1;
//[1,2,3,2,4,2,5,2,3]
for(int i = 1;i<numbers.size();++i){
if(time == 0){
temp = numbers[i];
time = 1;
}else if(temp == numbers[i]){
++time;
}else{
--time;
}
}
// 判断 temp 是否符合要求
int count = 0;
for(int i = 0;i<numbers.size();++i){
if(temp == numbers[i]){
++count;
}
}
if(count > numbers.size()/2){
return temp;
}else{
return 0;
}
}
解法三:python 低效解法
以下是python 懒人解法,pyhton 时间复杂复很大,效率太低了,有个好处就是简便!
import collections
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
tmp = collections.Counter(numbers)
x = len(numbers)/2
for k, v in tmp.items():
if v > x:
return k
return 0 代码解释:
第 4 行:建立一个映射字典的关系
Counter({2: 4, 1: 1, 3: 1, 4: 1})
第六行:k 代表的是 key ,v 代表的是 value ;
所以如果 v 大于 x 的话则返回 k ,如果循环出来就说明没有符合的值,则返回0

京公网安备 11010502036488号