Leetcode 1093:大样本统计(超详细的解法!!!)

我们对 0255 之间的整数进行采样,并将结果存储在数组 count 中:count[k] 就是整数 k 的采样个数。

我们以 浮点数 数组的形式,分别返回样本的最小值、最大值、平均值、中位数和众数。其中,众数是保证唯一的。

我们先来回顾一下中位数的知识:

  • 如果样本中的元素有序,并且元素数量为奇数时,中位数为最中间的那个元素;
  • 如果样本中的元素有序,并且元素数量为偶数时,中位数为中间的两个元素的平均值。

示例 1:

输入:count = [0,1,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
输出:[1.00000,3.00000,2.37500,2.50000,3.00000]

示例 2:

输入:count = [0,4,3,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
输出:[1.00000,4.00000,2.18182,2.00000,1.00000]

提示:

  1. count.length == 256
  2. 1 <= sum(count) <= 10^9
  3. 计数表示的众数是唯一的
  4. 答案与真实值误差在 10^-5 以内就会被视为正确答案

解题思路

这个问题的关键在于题目意思的理解,什么是采样count[k] 就是整数 k 的采样个数。

那么最大值和最小值就很好处理,我们只需要遍历count判断最小的非0index在哪?最大的非0index在哪。

平均值也非常好处理,对于所有非0count,我们通过累加count[k]*index得到所有数的和,然后除上所有非0count和( ∑ n = 0 256 c o u n t [ n ] ( w h i l e   c o u n t [ n ] ! = 0 ) \sum_{n=0}^{256}count[n](while\ count[n]!=0) n=0256count[n](while count[n]!=0))即可。

众数也非常容易,只需统计count值最大时的index即可。

中位数的处理相对麻烦一些,因为需要分非0count和是奇数还是偶数两种情况。我们首先假设非0count和为cnt,那么如果cnt是奇数的话,我们只需要找到cnt//2的位置即可,这非常容易办到,也就是不断累加count的值,直到累加和超过(大于等于)cnt//2。如果cnt是偶数的话,我们需要找到cnt//2+1cnt//2的位置,找法和奇数情况相同,不过需要找两次(我们可以放到一个循环中做两次判断)。

class Solution:
    def sampleStats(self, count: List[int]) -> List[float]:
        res = [255, 0, 0, 0, 0]
        sum_all = sum(count)
        l, r = sum_all//2, sum_all//2
        if not (sum_all & 1):
            r += 1
            
        pre, lc = 0, 0
        for i, val in enumerate(count):
            if val:
                res[0] = min(res[0], i)
                res[1] = i
            res[2] += i * val/sum_all
            
            if pre < l and pre + val >= l:
                res[3] += i/2
            if pre < r and pre + val >= r:
                res[3] += i/2
            pre += val
            
            if val > lc:
                lc = val
                res[4] = i
        return [float(i) for i in res]

我将该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

你可能感兴趣的:(Problems,leetcode解题指南,leetcode)