LeetCode 大样本统计
大样本统计
我们对 0 到 255 之间的整数进行采样,并将结果存储在数组 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]
提示:
count.length == 256
1 <= sum(count) <= 10^9
计数表示的众数是唯一的
答案与真实值误差在 10^-5 以内就会被视为正确答案
题目分析
第一次做这道题,倒不是因为它很难,而是因为太难通过测试了。首先,这是一道中等题目,首先我就想到了将这个数组还原。例如[0,1,3,4]还原成[1,2,2,2,3,3,3,3]但是,这显然不行,空间复杂度和时间复杂度太高。刚开始我想到了找链表中间结点的快慢指针法,但是我发现,这并不可行。其实求最大最小值,总数,平均数很简单。这道题难就难在怎么求中位数,我想了很久,最后用双指针法将这题解决了。
首先,我们分别在开头与末尾设置一个左指针和右指针(注意,指向的是非0的count),然后如果左指针即count[left]<count[right],左指针右移,并且将右指针的值更新为count[right]-count[left]。对于右指针大于左指针的情况操作类似。
关键来了:我们究竟要如何区分偶数和奇数的情况呢。得分两种情况去考虑
- 退出循环时,左指针等于右指针,意味着为奇数,直接取该数作为中位数即可
- 退出循环时,左指针大于右指针(刚开始左指针是小于右指针的),中位数取
(left+right)/2。
注意:除此之外,我们需要考虑的还有整数溢出问题(我被这个卡了很久,由于部分的测试样例太大)。因此,我们在这句中sum = sum + long(i)*(long)count[i];必须这么写,相乘才不会整数溢出。
class Solution {
public:
vector<double> sampleStats(vector<int>& count) {
vector<double> ans(5);
int max = 0;
int count2 = 0;//统计数量
long sum = 0;
bool flag = true;
for(int i =0;i<=255;i++){
if(count[i]!=0 && flag){
ans[0] = i;
sum = sum + long(i)*(long)count[i];
count2 += count[i];
ans[1] = i;
flag = false;
if (count[i]>max){
max = count[i];
ans[4] = i;
}
continue;
}
else if(count[i]!=0){
sum = sum + long(i)*(long)count[i];
count2 += count[i];
ans[1] = i;
if (count[i]>max){
max = count[i];
ans[4] = i;
}
}
//平均值
ans[2]=double(sum)/double(count2);
}
//计算中位数
double mid;
int left = 0;
int right = 255;
while(left<right){
while(count[left]==0){
left++;
}
while(count[right]==0){
right--;
}
if (count[left]>count[right]){
count[left] -= count[right];
do{
right--;
}while(count[right]==0);
}
else if (count[left]<count[right]){
count[right] -= count[left];
do{
left++;
}while(count[left]==0);
}
else{
do{
right--;
}while(count[right]==0);
do{
left++;
}while(count[left]==0);
}
}
if(left==right){
mid = left;
}
else{
mid = (double(left)+double(right))/2;
}
ans[3]=mid;
return ans;
}
};

浙公网安备 33010602011771号