剑指 day 2【JZ39 数组中出现次数超过一半的数字】

在这里插入图片描述

解题思路

  1. 思路一:遍历一遍数组并用哈希表统计次数,然后遍历一遍哈希表去查找次数符合题目要求的数 时间复杂度:o(n),空间复杂度o(n)
  2. 思路二:先排序然后取中间的元素,则必为符合题意的数 时间复杂度:o(nlogn),空间复杂度o(1)或0(n)
  3. 思路三:快排思想,停止条件是partition的k正好为长度的一半的索引值,此时的索引对应的值必定符合题意。相较于思路二,该算法并不需要对数组中的所有值排序

【反证法:假设该值value大于题意值m,则前半区间必定小于value,m必定全部位于前半区间,由于m的个数大于区间长度一半,那么m必定会覆盖到value,value的索引值会被挤到大于区间一半,与假设不符;value<m同理,m位于后半段并必定会使value索引值往前靠;综上,当k为区间长度一半时,array[k]必为m】
代码实现:[实际提交时会超时,看了下超时用例是会使得快排复杂度为o(n^2)的情况emm]

    def MoreThanHalfNum_Solution(self , numbers: List[int]) -> int:
        start, end = 0, len(numbers)-1
        while True:
            m = self.quicksort(numbers, start, end)
            if m == len(numbers)//2:
                print(numbers)
                return numbers[len(numbers)//2]
            elif m < len(numbers)//2:
                start = m + 1
            else:
                end = m - 1
        
    def quicksort(self, numbers, start, end)-> int:
        i, j, pivot = start, end, numbers[start]
        while i < j:
            while numbers[j] >= pivot and j > i: j-=1
            numbers[i] = numbers[j]
            while numbers[i] <= pivot and j > i: i+=1
            numbers[j] = numbers[i]
        numbers[i] = pivot
        return i
  1. 思路四:
    遇见一个友军就抱成团,遇见一个敌军就同归于尽,那么最后战场上剩余的肯定就是人数(出现次数)最多的那个队伍(数字)的思想。
    先选取一个候选者,然后往后遍历,当遇见一个相同的数计数器就加一否则减一,当计数器为0时,更换下一位位候选者,重新操作,直至遍历完所有元素,最后一个候选者一定是数量过半的数。
    证明:假设第一个候选者是要找的x,那么当count为0时,这段区间友军和敌军各损一半,后半段还是友军比敌军多;假设第一个候选者不是x,那么当count为0时,消耗的敌军一定比友军多【因为可能还有别的敌军去消耗他们】,剩下区间的友军也一定比敌军多。由于每次剩余区间的友军数>敌军,那么一定不可能出现敌军候选者遍历到元素最后的情况,最终只能是友军剩(胜)。
    该方法十分巧妙,充分利用题目条件,时间复杂度是o(n),空间复杂度是o(1)在这里插入图片描述while写法
class Solution:
    def MoreThanHalfNum_Solution(self , numbers: List[int]) -> int:
        i, lenth = 0, len(numbers)
        while i < lenth:
            candidate = numbers[i]
            count = 1
            i += 1
            while i < lenth and count != 0: 
                count = count+1 if numbers[i] == candidate else count-1
                i += 1
        return candidate

for写法

class Solution:
    def MoreThanHalfNum_Solution(self , numbers: List[int]) -> int:
        count = 0
        for number in numbers:
            if count == 0:
                candidate = number
            count = count+1 if number == candidate else count-1
        return candidate
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值