题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
思路1
超过一半的数字一定位于有序数组的中间(向下或向上取整),否则不可能会超过一半
- 先对数组排序
- 得到中位数后,求indexOf,lastIndexOf
- 计算长度是否超过一半
时间复杂度取决于排序算法,平均时间复杂度用堆排序也会是 O(nlgn)
function MoreThanHalfNum_Solution(numbers) {
if (!numbers.length)
return 0
numbers.sort()
let mid = numbers[ Math.floor( numbers.length / 2 ) ]
let length = numbers.lastIndexOf(mid) - numbers.indexOf(mid) + 1
return length > numbers.length / 2 ? mid : 0
}
思路2
利用几次 O(n) 循环计算次数和查找众数,再判断众数的次数
- 计算每个数字的次数
- 找出众数和众数的次数
- 判断次数是否超过一半
其中,在计算每个数子的次数时,我用了Object的key不重复的特性来记录每个数字出现的次数,只需要一次遍历;查找众数也是一次遍历。时间复杂度O(n)
function MoreThanHalfNum_Solution(numbers) {
if (!numbers.length)
return 0
let record = {}
numbers.forEach(num => {
record[num] ? record[num] = 1 : record[num]++
})
let max = Number.MIN_VALUE
let mode = numbers[0]
for (let key in record) {
if (record[key] > max) {
max = record[key]
mode = key
}
}
return max > numbers.length / 2 ? mode : 0
}