【刷题打卡】1093. 大样本统计

254 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

一、题目描述:

1093. 大样本统计 - 力扣(LeetCode) (leetcode-cn.com)

我们对 0 到 255 之间的整数进行采样,并将结果存储在数组 count 中:count[k] 就是整数 k 在样本中出现的次数。

计算以下统计数据:

  • minimum :样本中的最小元素。
  • maximum :样品中的最大元素。
  • mean :样本的平均值,计算为所有元素的总和除以元素总数。
  • median :
    • 如果样本的元素个数是奇数,那么一旦样本排序后,中位数 median 就是中间的元素。
    • 如果样本中有偶数个元素,那么中位数median 就是样本排序后中间两个元素的平均值。
  • mode :样本中出现次数最多的数字。保众数是 唯一 的。 以浮点数数组的形式返回样本的统计信息 [minimum, maximum, mean, median, mode] 。与真实答案误差在 10-5 内的答案都可以通过。

 

示例 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]
解释:用count表示的样本为[1,2,2,2,3,3,3,3,3]。
最小值和最大值分别为1和3。
均值是(1+2+2+2+3+3+3+3) / 8 = 19 / 8 = 2.375。
因为样本的大小是偶数,所以中位数是中间两个元素2和3的平均值,也就是2.5。
众数为3,因为它在样本中出现的次数最多。

示例 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]
解释:用count表示的样本为[1,1,1,1,2,2,3,3,3,4,4]。
最小值为1,最大值为4。
平均数是(1+1+1+1+2+2+2+3+3+4+4)/ 11 = 24 / 11 = 2.18181818…(为了显示,输出显示了整数2.18182)。
因为样本的大小是奇数,所以中值是中间元素2。
众数为1,因为它在样本中出现的次数最多。

提示:

  • count.length == 256
  • 0 <= count[i] <= 10^9
  • 1 <= sum(count) <= 10^9
  •  count 的众数是 唯一 的

二、思路分析:

这是一个类似hash表的表示方法,如count[10]=5表示数字10出现了五次。

思路:

先正序找到第一个不为零的元素,此时count[i]>0,表示i元素出现过,因为是第一个找到的所以肯定是最小值。

同理倒序找到最大值。

然后扫描索引为最小值到最大值之间的数组,0-min,max-255都是0,不用管。 用变量cnt、sum分别记数字出现次数和数字总合,以及count[i]最大值与所对应的i。

扫描完之后一除就是平均数,上面记下的i是众数。

所有数字出现次数对2取余数,如果余1说明中位数只有一个,余0说明有两个取平均。 然后再次扫描,每次在cnt中减去count[i],当cnt<=count[i]时说明在当前i取到中位数。 两个中位数的的找法相同。

三、AC 代码:

typedef long long ll;
typedef double db;
class Solution {
public:
    vector<double> sampleStats(vector<int>& count) {
        int n=count.size();
        ll sum=0;
        int cnt=0,maxx=0,temp=0;
        int half=-1,halfcount=0;
        vector<int>res;
        res.reserve(256);
        for(int i=0;i<n;i++){
            if(count[i]==0)continue;
            res.push_back(i);
            sum+=count[i]*i;
            cnt+=count[i];
            if(count[i]>temp){
                temp=count[i];
                maxx=i;
            }
            while(halfcount==0||cnt/2>halfcount){
                half++;
                halfcount+=count[res[half]];//halfcount表式的含义是拥有多少个数据
            }
        }
        //下面是判断中位数的,因为上面的while操作,所以我们再进行中位数的判断会非常的容易。。。
        db med;
        if(cnt/2==halfcount){//这个表示的是,我们拥有偶数个数据
            med=(db)0.5*(res[half]+res[half+1]);
        }else{
            med=(db)res[half];
        }
        vector<db>ans;
        ans.push_back(1.0*res[0]);
        ans.push_back(1.0*res.back());
        ans.push_back(1.0*sum/cnt);
        ans.push_back(med);
        ans.push_back(1.0*maxx);
        return ans;
    }
};