【剑指Offer】26数组中出现次数超过一半的数字
题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
时间限制:1秒;空间限制:32768K;本题知识点:数组
解题思路
思路一
先通过集合set得到去重后出现的数字,然后在原数组中循环统计每个数字出现的次数,最后判断是否超过数组长度一半。
Python代码:
# -*- coding:utf-8 -*-
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
# write code here
num = list(set(numbers)) #去重
count = [] #记录个数
for k in range(len(num)):
count.append(0)
for i in range(len(numbers)):
for j in range(len(count)):
if numbers[i] == num[j]:
count[j] += 1
for k in range(len(count)):
if count[k] > len(numbers)//2:
return num[k]
return 0
思路二
上述做法不是最优算法,时间复杂度太大了。可用以下思路去做,时间复杂度O(n):
首先,如果存在一个数字出现次数超过数组长度的一半,那么它一定比其他所有数字出现的次数都要多。采用阵地攻守的思想:第一个数字作为第一个士兵,守阵地,count = 1;遇到相同元素,count++;遇到不相同元素,即为敌人,同归于尽,count--;当遇到count为0的情况,又以新的i值作为守阵地的士兵,继续下去,到最后还留在阵地上的士兵,有可能是主元素。再通过一次循环统计出现次数,判断出现次数是否超过数组长度的一半。
Python代码:
# -*- coding:utf-8 -*-
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
# write code here
num = numbers[0] #初值为第一个数
count = 1 #计数
for i in range(1, len(numbers)):
# 如果是相同的元素
if numbers[i] == num:
count += 1
else:
count -= 1
if count == -1:
count = 1
num = numbers[i]
s = 0
for i in range(0, len(numbers)):
if numbers[i] == num:
s += 1
if s > len(numbers)//2:
return num
else:
return 0