剑指offer第二版(Python3)--面试题39 : 数组中出现次数超过一半的数字

第2章 面试需要的基础知识

第3章 高质量的代码

第4章 解决面试题的思路

  面试题27:二叉树的镜像
  面试题29:顺时针打印矩阵
  面试题30 :包含min函数的栈
  面试题31:栈的压入、弹出序列
  面试题32:上往下打印二叉树
  面试题33: 二叉搜索树的后序遍历序列
  面试题34: 二叉树中和为某一值的路径
  面试题35:复杂链表的复制
  面试题36:二叉搜索树与双向链表
  面试题38:字符串的排列

第5章 优化时间和空间效率

第6章 面试中的各项能力

第7章 两个面试案例


题目描述

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

解题思路
牛客网
方法一:
  数组中有一个数字出现的次数超过数组长度的一半,所以它出现的次数比其它数出现的次数总和还多。考虑在遍历数组时保存两个值:一个是数组中的一个数字,另一个是次数。
  当我们遍历到下一个数字时,如果下一个数字和我们之前保存的数字相同,则次数加1;如果不同,则次数减1。如果次数为零,则需要保存下一个数字,并把次数设为1。这样要找的数字可能是最后一次把次数设为1时对应的数字,还需要统计这个数字在数组中的数量才能确认。
实战

class Solution:
    def MoreThanHalfNum_Solution(self, numbers):
        # write code here
        length = len(numbers)
        i = 0
        counts = 0
        while i < length:
            if counts == 0:
                digit = numbers[i]
                i += 1
                counts = 1
                continue
            if numbers[i] != digit:
                counts -= 1
            else:
                counts += 1
            i += 1
        
        counts = 0
        for num in numbers:
            if num == digit:
                counts += 1
        if counts > length >> 1:
            return digit
        return 0

方法二:
  受快速排序启发,有成熟的得到数组中任意第k大数字的算法,且时间复杂度为O(n)。如果数组有一个数其数量超过数组长度一半,那么排序后的数组其中间位置的数一定就是那个次数超过一半的数,所以这道题可以引申为寻找排序数组的中间位置数。
  我们先随机选取一个数字,然后调整数组顺序,使得比选中数字大的数在其右边,小的数在其左边。如果选中的数其索引恰好为n/2,则这个数就是中间位置数;如果其索引大于n/2,那么中间位置数在这个数的左边,然后继续去左边数组中查找;否则中间位置数在其右边,继续去右边数组中查找。这是一个典型的递归过程。
实战

class Solution:
    def MoreThanHalfNum_Solution(self, numbers):
        # write code here
        if not numbers:
            return numbers
        
        def recc(begin, end):
            if begin >= end:
                return numbers[begin]
            index = begin
            for i in range(begin+1, end+1):
                if numbers[index] > numbers[i]:
                    numbers[index], numbers[i] = numbers[i], numbers[index]
                    index = i 
            if index == length >> 1:
                return numbers[index]
            if index > length >> 1:
                num = recc(begin, index-1)
            else:
                num = recc(index+1, end)
            return num
        
        length = len(numbers)
        number = recc(0, length-1)
        counts = 0
        for i in range(length):
            if number == numbers[i]:
                counts += 1
        if counts > length >> 1:
            return number
        return 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值