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

# -*- coding: utf-8 -*-# @Time : 2019-07-08 17:21# @Author : Jayce Wong# @ProjectName : job# @FileName : MoreThanHalfNum.py# @Blog : https://blog.51cto.com/jayce1111# @Github : https://github.com/SysuJayceclass Solution: """ 解法1: 要寻找一个数组中出现次数大于一半的元素,那么很明显如果在一个有序数组中,这个元素会出现在数组中 间,也就是统计意义上的中位数。那么通过寻找位于有序数组的中间的那个元素就可以确定这个中位数。 解法2: 如果一个元素出现次数大于一半,那么这个元素的出现次数一定大于其他所有元素的出现次数之和。 因此,如果我们对上一次出现的元素进行统计,最后剩下的那个元素就是我们的目标元素。 具体来说,如果当前出现的元素和之前保存的元素不一样,那么次数-1,反之+1.如果次数减到0了,那么 保存当前新出现的元素。 """ def MoreThanHalfNum_Solution2(self, numbers): def partition(begin, stop): # 这个函数的作用就是确定一个元素在有序数组中的正确位置,可以用来寻找位于有序数组正中 # 间的元素 pos = begin for i in range(begin, stop): if numbers[i] < numbers[stop]: numbers[pos], numbers[i] = numbers[i], numbers[pos] pos += 1 numbers[stop], numbers[pos] = numbers[pos], numbers[stop] return pos if not numbers: return 0 mid = len(numbers) >> 1 start, end = 0, len(numbers) - 1 index = partition(start, end) while index != mid: # 如果排好序的那个元素不在正中间,那么就根据它的位置重新确定待排序的子数组 if index > mid: end = index - 1 else: start = index + 1 index = partition(start, end) # 注意要检查找到的目标元素是否符合要求 count = 0 for num in numbers: if num == numbers[index]: count += 1 return numbers[index] if 2 * count > len(numbers) else 0 def MoreThanHalfNum_Solution(self, numbers): if not numbers: return 0 count = 1 ans = numbers[0] for i in range(1, len(numbers)): # 如果当前元素和保存的元素一致,那么count+1,反之-1. if numbers[i] == ans: count += 1 else: count -= 1 # 如果count减到0,那么用当前元素替换之前保存的元素 if count <= 0: ans = numbers[i] # 注意要检查找到的目标元素是否符合要求 count = 0 for num in numbers: if num == ans: count += 1 return ans if count * 2 > len(numbers) else 0def main(): nums = [1, 2, 3, 2, 2, 2, 5, 4, 2] solution = Solution() print(solution.MoreThanHalfNum_Solution(nums))if __name__ == '__main__': main()