• leetcode:1157. 子数组中占绝大多数的元素【暴力遍历 + 随机算法相信概率】


    题目截图

    在这里插入图片描述

    在这里插入图片描述

    题目分析

    • 一个很暴力的思路就是把每个num出现的idx记录起来,然后按出现的频率排序优化
    • 每次query,遍历每个元素和频率,频率如果已经比threhold小就没有看的必要,直接break
    • 如果比它大,我们通过d获得其ids序列,左右二分其left和right得到两个下标l和r
    • 如果r - l >= threhold说明中间夹着大于threhold个,就满足了
    • 但是这个几乎超时
    • 特别地,我们可以考虑随机算法
    • 由于一个区间要么存在一个答案,要么不存在答案
    • 也就是由于2 * threhold > len([l, r])
    • 这样的话如果存在,抽不到一个符合的num的概率小于0.5
    • 如果超过k次都抽不到且又存在答案的话,这个概率是小于0.5 ^ k
    • 所以不妨k = 30,如果超过30次扔找不到答案,我们就认为它没有答案;答案在arr[l:r + 1]中随机抽取

    暴力二分

    class MajorityChecker:
        # threshold过半最多只有一个
        def __init__(self, arr: List[int]):
            # 记录每个值出现的index
            self.d = defaultdict(list)
            for i, v in enumerate(arr):
                self.d[v].append(i)
            # 出现频率的统计(从大到小)
            self.freq = sorted([(len(ids), value) for value, ids in self.d.items()], reverse = True)
    
    
        def query(self, left: int, right: int, threshold: int) -> int:
            for f, v in self.freq:
                if f < threshold: break
                ids = self.d[v]
                l = bisect_left(ids, left)
                r = bisect_right(ids, right)
                if r - l >= threshold:
                    return v
            return -1
    
    
    
    # Your MajorityChecker object will be instantiated and called as such:
    # obj = MajorityChecker(arr)
    # param_1 = obj.query(left,right,threshold)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    随机二分

    class MajorityChecker:
        # threshold过半最多只有一个
        def __init__(self, arr: List[int]):
            # 记录每个值出现的index
            self.arr = arr
            self.d = defaultdict(list)
            for i, v in enumerate(arr):
                self.d[v].append(i)
            # 出现频率的统计(从大到小)
            # self.freq = sorted([(len(ids), value) for value, ids in self.d.items()], reverse = True)
    
    
        def query(self, left: int, right: int, threshold: int) -> int:
            # 随机从[l, r]抽一个数
            # 如果存在答案,那么抽不到答案的概率小于0.5
            # 多次都抽不到答案,认为没有答案,返回-1
            Round = 30
            for _ in range(Round):
                choice = self.arr[random.randint(left, right)]
                l = bisect_left(self.d[choice], left)
                r = bisect_right(self.d[choice], right)
                if r - l >= threshold:
                    return choice
            return -1
    
    
    
    # Your MajorityChecker object will be instantiated and called as such:
    # obj = MajorityChecker(arr)
    # param_1 = obj.query(left,right,threshold)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    总结

    • 使用随机算法优化
    • 通过概率论可知,随机算法确实是概率正确的
  • 相关阅读:
    <c++> &引用概念 | 引用用法 | 引用与指针区别
    AtCoder Beginner Contest 267 (A~D)
    springboot actuator:开放全部(部分)端点、端点映射、端点保护
    【Python】操作符梅花号*、乘号*的用法汇总与小结
    【软考】11.2 开发方法/产品线/软件复用/逆向工程
    LeetCode144二叉树的前序遍历,94二叉树的中序遍历,145二叉树的后序遍历
    Vue中使用 Aplayer 和 Metingjs 添加音乐插件
    Windows 11 system tray do not respond to clicks
    JavaScript事件触发
    springcloudalibaba架构(25):RocketMQ事务消息
  • 原文地址:https://blog.csdn.net/weixin_40986490/article/details/128041903