Day28:数组中出现次数超过一半的数字
剑指Offer_编程题——数组中出现次数超过一半的数字
题目描述:
数组中有一个数字出现的次数超过数组长度的一半,请输出这个数字。例如,输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半。因此输出2.。如果不存在则输出0.
具体要求:
时间限制: C/C++ 1秒,其他语言2秒 空间限制: C/C++32M,其他语言64M
具体思路:
思路一 这是我们最常规的一种思维,最简单的一种算法。就是定义一个计数器count来计数,首先遍历整个数组。一次计算出现的次数。将出现最大的数字的次数与数组长度的一半相比较。如果大于数组一半的长度,输出这个数,否则输出0,具体我们用Java来将其实现。
public class Solution{
public int MoreThanHalfNum_Solution(int [] array){
int len = array.length;
int k = array[0];
int count = 1;
for(int i = 1; i < len; i++){
if(k == array[i]){
count++;
}
else if(k != array[i]){
count--;
}if(count == 0){
k = array[i];
count = 1;
}
}
int num = 0;
for(int j = 0; j < len; j++){
if(array[j] == k){
num++;
}
}
if(num * 2 <= len){
return 0;
}else{
return k;
}
}
}
代码效果图如图所示:
思路二 先用Boyer-Moore Majority-Vote Algorithm算法,即多数投票问题,找出序列中出现次数超过一半的元素。在判断题目的条件时,看是否出现次数超过一半,超过则存在。并不超过则不存在。 Boyer-Moore Majority Vote Algorithm算法: 使用count来统计一个元素出现的次数,当遍历到的元素和统计元素相等时,令count++,否则令count–。如果前面查找了i个元素,且count==0,说明前i个元素没有most,或者有most,但是出现的次数小于i/2,因为如果i/2超过数组一半时count就一定不会为0.此时剩下的n-i个元素中,most数目依然多于(n-i)/2,因此继续查找就能找出majority。我们用java将其实现
public class Solution{
public int MoreThanHalfNum_Solution(int []array){
if(array == null || array.length == 0){
return 0;
}
int most = array[0];
int count = 1;
for(int i = 1; i < array.length; i++){
count = most == array[i]?count+1:count-1;
if(count == 0){
most = array[i];
count = 1;
}
}
count = 0;
for(int i = 0; i < array.length;i++){
if(most == array[i]){
count++;
}
}
return count > array.length/2?most:0;
}
}
代码效果图如图所示:
思路三 可以采用Python中的字典的方法,元素对应key,出现的次数对应val。具体实现如下:
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
if numbers == []:
return 0
dictonary = {}
dictonary = dictonary.fromkeys(numbers, 0)
for num in numbers:
dictonary[num] += 1
for key in dictonary.keys():
if dictonary[key] * 2 > len(numbers):
return key
return 0
代码效果图如图所示:
思路四 如果一个数字的个数超过半数,那么N/2大的数字一定是这个数字,因此用这个方法找出第N/2大的数字,然后判断这个数字出现的次数是不是满足大于长度的二分之一。(N维数组的长度)。具体用python将其实现:
class Solution:
def partitionOfK(self, numbers, start, end, k):
if k < 0 or numbers == [] or start < 0 or end >= len(numbers) or k > end:
return None
low = start
high = end
key = numbers[start]
while low < high:
while low < high and numbers[high] >= key:
high -= 1
numbers[low] = numbers[high]
while low < high and numbers[low] <= key:
low += 1
numbers[high] = numbers[low]
numbers[low] = key
if low < k:
return self.partitionOfK(numbers, start + 1, end, k)
elif low > k:
return self.partitionOfK(numbers, start, end - 1, k)
else:
return numbers[low]
def checkMoreThanHalf(self, numbers, num):
times = 0
for number in numbers:
if num == number:
times += 1
if times * 2 <= len(numbers):
return False
return True
def MoreThanHalfNum_Solution(self, numbers):
# write code here
if numbers == []:
return 0
result = self.partitionOfK(numbers, 0, len(numbers) - 1, len(numbers) >> 1)
if self.checkMoreThanHalf(numbers, result):
return result
else:
return 0
代码效果图如图所示:
思路五 数组中如果有一个数字出现的次数超过数组长度的一半,也就是说他出现的次数比其他所有的数字出现的次数和还要多。因此当我们遍历到下一个数字的时候,如果相同,次数加1,不同次数减1,知道为0,如果为0,那么保存下一个数字,并把次数设置为1,找的就是最后设置为1 的数字。接下来用python实现:
class Solution:
def checkMoreThanHalf(self, numbers, num):
times = 0
for number in numbers:
if num == number:
times += 1
if times * 2 <= len(numbers):
return False
return True
def MoreThanHalfNum_Solution(self, numbers):
if numbers == []:
return 0
result = numbers[0]
times = 1
for i in range(1, len(numbers)):
if times == 0:
result = numbers[i]
times = 1
elif numbers[i] == result:
times += 1
else:
times -= 1
if self.checkMoreThanHalf(numbers, result):
return result
else:
return 0
代码效果图如图所示:
总结
本道题主要考察数组的实际应用,一道很简单的算法编程题,但是本文一共应用了5种解法,其中前两种方法是用java实现的,并且还应用了著名的投票选举算法。后三种方法是用python实现的。三种方法其中用到了字典,以及还有两种相似但完全不同的方法。因此,我们在做题的时候,应该多次尝试各种方法,扩展自己的思维,写出优质的代码。总之,我们要继续加油,争取早日找到工作,Good Luck!!!
参考文献
[1] 喜欢唱跳有错吗 [2] IDEA_TEYU_1112 [3] hustfc
- mysql几种存储引擎介绍
- Java基础-21(02)总结字符流,IO流编码问题,实用案例必做一遍
- DeDeCMS v5.7 密码修改漏洞分析
- Java基础-20(01)总结,递归,IO流
- 一个Oracle bug的手工修复(r6笔记第59天)
- 由drop datafile导致的oracle bug(r6笔记第56天)
- Java中static关键字的作用
- Java基础-20(02)总结,递归,IO流
- Hive四种数据导入方式
- 34c3 部分Web Writeup
- 原来Oracle也不喜欢“蜀黍"(r6笔记第54天)
- Java基础19(01)总结IO流,异常try…catch,throws,File类
- 使用shell生成orabbix自动化配置脚本(r6笔记第53天)
- 现在 tensorflow 和 mxnet 很火,是否还有必要学习 scikit-learn 等框架?
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 5 分钟教你用 Python 实现贪吃蛇!
- Python 基础(八):与时间相关的模块
- 用 Python 实现一场环保无污染的烟花秀
- Python 基础(九):函数
- Python 基础(十二):文件基本操作
- Python 基础(十三):os 模块
- Python 基础(十四):错误和异常
- Python 基础(十五):枚举
- 一个老程序员的30年生涯回顾
- 经典 90 坦克大战 Python 版实现(支持单双人模式)
- Python 基础(十六):迭代器与生成器
- MySQL information_schema详解 COLUMNS
- MySQL information_schema详解 COLUMN_PRIVILEGES
- 一分钟学Python|Python的字典
- MySQL information_schema详解 ENGINES