题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
思路
《剑指offer》P163
-
方法一:
使用快排的思想,先随机选择一个数字,进行一趟排序,使得该数字左边的数都比其小,右边的数都比其大,然后判断该数字的index
是否位于数组中间,如果是,则计算出现的次数,大于长度的一半则返回该数。否则,如果index
>mid
则将左边的数字再排序,如果index
<mid
则将右边的数字再排序。时间复杂度
O(NlogN)
-
方法二:
遍历一趟数组,保存两个值:一个是当前的数字n
,一个是次数cnt
。如果当前数字与n
相等,则cnt++
,不相等则cnt--
,如果cnt
减为0,则将n
重新置为当前的数字,cnt=1
。
遍历完毕后,n
的值即为候选数,然后再判断该数在数组中的次数。
code
方法一:
# -*- coding:utf-8 -*-
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
# write code here
mid = len(numbers) / 2
index = self.Parition(numbers, 0, len(numbers) - 1)
while index != mid:
if index < mid:
index = self.Parition(numbers, index + 1, len(numbers) - 1)
else:
index = self.Parition(numbers, 0, index - 1)
if self.CheckNumber(numbers, numbers[index]):
return numbers[index]
else:
return 0
def Parition(self, arr, low, high):
index = low - 1
for i in range(low, high):
if arr[i] <= arr[high]:
index += 1
arr[i], arr[index] = arr[index], arr[i]
index += 1
arr[index], arr[high] = arr[high], arr[index]
return index
def CheckNumber(self, arr, number):
cnt = 0
for n in arr:
if n == number:
cnt += 1
if cnt * 2 > len(arr):
return True
return False
方法二
# -*- coding:utf-8 -*-
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
# write code here
if not numbers:
return 0
cnt = 1
n = numbers[0]
for x in numbers[1:]:
if x == n:
cnt += 1
else:
cnt -= 1
if cnt == 0:
n = x
cnt += 1
if self.CheckNumber(numbers, n):
return n
else:
return 0
def CheckNumber(self, arr, number):
cnt = 0
for n in arr:
if n == number:
cnt += 1
if cnt * 2 > len(arr):
return True
return False