【剑指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
原文地址:https://www.cnblogs.com/yucen/p/9912034.html