1157. Online Majority Element In Subarray

88 篇文章 0 订阅
19 篇文章 0 订阅

Implementing the class MajorityChecker, which has the following API:

  • MajorityChecker(int[] arr) constructs an instance of MajorityChecker with the given array arr;
  • int query(int left, int right, int threshold) has arguments such that:
    • 0 <= left <= right < arr.length representing a subarray of arr;
    • 2 * threshold > right - left + 1, ie. the threshold is always a strict majority of the length of the subarray

Each query(...) returns the element in arr[left], arr[left+1], ..., arr[right] that occurs at least threshold times, or -1 if no such element exists.

 

Example:

MajorityChecker majorityChecker = new MajorityChecker([1,1,2,2,1,1]);
majorityChecker.query(0,5,4); // returns 1
majorityChecker.query(0,3,3); // returns -1
majorityChecker.query(2,3,2); // returns 2

 

Constraints:

  • 1 <= arr.length <= 20000
  • 1 <= arr[i] <= 20000
  • For each query, 0 <= left <= right < len(arr)
  • For each query, 2 * threshold > right - left + 1
  • The number of queries is at most 10000

Discuss

思路:神奇的题目,一开始想套用running sum求majority number那一套,最坏时间复杂度10000*20000,同时也会MLE

class MajorityChecker(object):

    def __init__(self, arr):
        """
        :type arr: List[int]
        """
        self.memo={}
        self.arr = arr

    def query(self, left, right, threshold):
        """
        :type left: int
        :type right: int
        :type threshold: int
        :rtype: int
        """
        if left in self.memo: 
            if right not in self.memo[left]: return -1
            if self.memo[left][right][1]<threshold: return -1
            return self.memo[left][right][0]
        
        a = self.arr
        f = 1
        var = a[left]
        count = {a[left]:1}
        self.memo[left] = {left:(a[left],1)}
        
        i=left+1
        while i<=len(a)-1:
            count[a[i]] = count.get(a[i],0)+1
            if a[i]==var: f+=1
            else: f-=1
            
            if f!=0:
                self.memo[left][i]=(var, count[var])
                i+=1
            else:
                if i+1<=len(a)-1:
                    f=1
                    var=a[i+1]
                    count[a[i+1]] = count.get(a[i+1],0)+1
                    self.memo[left][i+1]=(var, count[var])
                    i+=2
        
        if right not in self.memo[left]: return -1
        if self.memo[left][right][1]<threshold: return -1
        return self.memo[left][right][0]


# Your MajorityChecker object will be instantiated and called as such:
majorityChecker = MajorityChecker([1,1,2,2,1,1])
print(majorityChecker.query(0,5,4))
print(majorityChecker.query(0,3,3))
print(majorityChecker.query(2,3,2))

Discussion里的正解是random选择[left,right]区间某个数,因为如果有majority,数目一定超过一半(2 * threshold > right - left + 1),被sample到的概率很大。然后二分搜索该element下index的上下界

比如随机选20次,一次都没选到majority的概率为(1/2)^20

import random
import bisect

class MajorityChecker(object):

    def __init__(self, arr):
        """
        :type arr: List[int]
        """
        self.arr = arr
        self.elem2index={}
        for i,v in enumerate(arr):
            if v not in self.elem2index: self.elem2index[v]=[]
            self.elem2index[v].append(i)

    def query(self, left, right, threshold):
        """
        :type left: int
        :type right: int
        :type threshold: int
        :rtype: int
        """
        for _ in range(20):
            a = self.arr[random.randint(left,right)]
            indexes = self.elem2index[a]
            l = bisect.bisect_left(indexes, left)
            r = bisect.bisect_right(indexes, right)
            if r-l>=threshold: return a
        return -1


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值