题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。因为数字2在数组中出现了5次,超过数组长度的一半,所以输出2。若是不存在则输出0。git
# -*- 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/SysuJayce class 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 0 def main(): nums = [1, 2, 3, 2, 2, 2, 5, 4, 2] solution = Solution() print(solution.MoreThanHalfNum_Solution(nums)) if __name__ == '__main__': main()