【剑指offer】028-数组中出现次数超过一半的数字

题目

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

方法

方法:使用题目数组的特性
参考:https://www.cnblogs.com/lliuye/p/9152597.html
时间复杂度:O(2n)

思路

符合题目条件的数组,存在一个数,出现的次数超过数组长度的一半。所以这个数组出现的次数比数组中的其他数组加起来的次数都多

那么我们就可以通过这个特性去寻找这个数。假设这个数为k。方法是,原数组下,k出现的次数大于数组长度的一半。删掉不同的两个数字,k出现的次数仍然会大于数组长度的一半。再删除两个不同的数字,仍然符合这样的规律。最后剩下的数字就是我们要找的k

具体方法 —— 栈的巧用

可以使用栈,遍历数组。每个元素先入栈,然后与前一个栈顶元素相比,如果不相等,则连续出栈,达到删除两个不同元素的效果。否则就保持入栈不变。遍历完数组之后,栈顶元素就是所找的k
PS:注意栈空的情况,直接入栈

其他考虑

上面使用栈的方法,可以找到符合题目要求的数组中的k。但是对于不符合题目要求的数组,比如不存在这样的k,那么遍历完数组之后的栈顶元素,就不是正确结果。所以,在遍历完数组后,我们需要使用栈顶元素重新遍历一遍数组,检查一遍是否栈顶元素出现次数大于数组长度的一半,不是则需要返回0

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function MoreThanHalfNum_Solution (numbers) {
// write code here
if (numbers.length < 1) {
return 0
}
let result = []
numbers.forEach(item => {
if (result.length > 0 && item !== result[0]) {
result.shift()
} else {
result.unshift(item)
}
})
let count = 0
numbers.forEach(item => {
if (item === result[0]) {
count++
}
})
return count > numbers.length / 2 ? result[0] : 0
}
文章作者: ptp
文章链接: https://youyingjie114.github.io/2019/11/07/jz-offer/jz-offer-028/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 PTP'S BLOG