题目链接
题目描述
给定一个由若干个监控样本首尾相接组成的浮点数序列。每个样本都严格包含 19 个浮点特征。任务是解析整个序列,并对 19 个特征中的每一列分别计算 8 个指定的统计量。
需要计算的统计量及其顺序:
mean: 算术平均值max: 最大值min: 最小值ptp: 极差 (max-min)std: 总体标准差var: 总体方差skew: 总体偏度kurt: 总体超峰度
公式说明:
为样本数。
var=std=skew=。若
std为 0,则skew为 0。kurt=。若
std为 0,则kurt为 0。
输入:
- 一行空格分隔的浮点数,总数是 19 的整数倍。
输出:
- 一行空格分隔的浮点数,共
个。
- 先输出第 0 列特征的 8 个统计量,然后是第 1 列,以此类推,直到第 18 列。
- 所有数值均保留两位小数。
解题思路
这是一个纯粹的数据处理和统计计算问题。核心在于正确地组织数据并实现题目要求的各个统计公式。
-
数据读取与重组
- 首先,一次性读取输入行中的所有浮点数,存入一个一维数组(或列表)
all_data中。 - 计算样本数量
。
- 为了便于按列计算,我们可以将一维的
all_data重组为一个的二维矩阵
data。data[i][j]表示第个样本的第
个特征值。
- 首先,一次性读取输入行中的所有浮点数,存入一个一维数组(或列表)
-
按列进行统计计算
- 外层循环遍历 19 个特征列(
colfrom 0 to 18)。 - 对于每一列,执行以下计算:
- 第一次遍历 (Pass 1):遍历该列的所有
个数据点。在这次遍历中,我们可以同时计算出
sum,max, 和min。 - 计算基础统计量:
mean = sum / Nptp = max - min
- 第二次遍历 (Pass 2):再次遍历该列的
个数据点,利用已经计算出的
mean来计算方差所需的平方和sum_sq_diff。sum_sq_diff += (value - mean) * (value - mean)
- 计算方差和标准差:
var = sum_sq_diff / Nstd = sqrt(var)
- 处理标准差为 0 的特殊情况:
- 如果
std约等于 0(需要考虑浮点数精度),则根据题目要求,skew和kurt都直接设为 0。
- 如果
- 第三次遍历 (Pass 3):如果
std不为 0,则需要第三次遍历来计算偏度和峰度。- 对于每个值,计算其标准化值
。
- 累加
和
到各自的总和
sum_cubed和sum_quartic中。
- 对于每个值,计算其标准化值
- 计算偏度和峰度:
skew = sum_cubed / Nkurt = sum_quartic / N - 3
- 第一次遍历 (Pass 1):遍历该列的所有
- 外层循环遍历 19 个特征列(
-
格式化输出
- 将每一列计算出的 8 个统计量按顺序存储起来。
- 所有计算完成后,遍历存储结果的列表,将每个数值格式化为保留两位小数的字符串,并用空格连接后一次性输出。
代码
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <cmath>
#include <iomanip>
#include <numeric>
#include <limits>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
string line;
getline(cin, line);
stringstream ss(line);
double num;
vector<double> all_data;
while (ss >> num) {
all_data.push_back(num);
}
int n_features = 19;
int n_samples = all_data.size() / n_features;
vector<vector<double>> data(n_samples, vector<double>(n_features));
for (int i = 0; i < all_data.size(); ++i) {
data[i / n_features][i % n_features] = all_data[i];
}
cout << fixed << setprecision(2);
for (int j = 0; j < n_features; ++j) {
vector<double> col_data(n_samples);
for (int i = 0; i < n_samples; ++i) {
col_data[i] = data[i][j];
}
// 第一次遍历:计算总和、最小值、最大值
double sum = 0.0;
double max_val = -numeric_limits<double>::infinity();
double min_val = numeric_limits<double>::infinity();
for (double val : col_data) {
sum += val;
if (val > max_val) max_val = val;
if (val < min_val) min_val = val;
}
double mean = sum / n_samples;
double ptp = max_val - min_val;
// 第二次遍历:计算方差
double sum_sq_diff = 0.0;
for (double val : col_data) {
sum_sq_diff += (val - mean) * (val - mean);
}
double var = sum_sq_diff / n_samples;
double std = sqrt(var);
double skew = 0.0;
double kurt = 0.0;
// 第三次遍历:计算偏度和峰度
if (std > 1e-9) {
double sum_cubed = 0.0;
double sum_quartic = 0.0;
for (double val : col_data) {
double z = (val - mean) / std;
sum_cubed += z * z * z;
sum_quartic += z * z * z * z;
}
skew = sum_cubed / n_samples;
kurt = sum_quartic / n_samples - 3.0;
}
cout << mean << " " << max_val << " " << min_val << " " << ptp << " "
<< std << " " << var << " " << skew << " " << kurt
<< (j == n_features - 1 ? "" : " ");
}
cout << endl;
return 0;
}
import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;
import java.lang.Math;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
List<Double> allData = new ArrayList<>();
while (sc.hasNextDouble()) {
allData.add(sc.nextDouble());
}
int nFeatures = 19;
int nSamples = allData.size() / nFeatures;
double[][] data = new double[nSamples][nFeatures];
for (int i = 0; i < allData.size(); i++) {
data[i / nFeatures][i % nFeatures] = allData.get(i);
}
StringBuilder sb = new StringBuilder();
for (int j = 0; j < nFeatures; j++) {
double[] colData = new double[nSamples];
for (int i = 0; i < nSamples; i++) {
colData[i] = data[i][j];
}
// 第一次遍历:计算总和、最小值、最大值
double sum = 0.0;
double maxVal = -Double.MAX_VALUE;
double minVal = Double.MAX_VALUE;
for (double val : colData) {
sum += val;
if (val > maxVal) maxVal = val;
if (val < minVal) minVal = val;
}
double mean = sum / nSamples;
double ptp = maxVal - minVal;
// 第二次遍历:计算方差
double sumSqDiff = 0.0;
for (double val : colData) {
sumSqDiff += (val - mean) * (val - mean);
}
double var = sumSqDiff / nSamples;
double std = Math.sqrt(var);
double skew = 0.0;
double kurt = 0.0;
// 第三次遍历:计算偏度和峰度
if (std > 1e-9) {
double sumCubed = 0.0;
double sumQuartic = 0.0;
for (double val : colData) {
double z = (val - mean) / std;
sumCubed += z * z * z;
sumQuartic += z * z * z * z;
}
skew = sumCubed / nSamples;
kurt = sumQuartic / nSamples - 3.0;
}
sb.append(String.format("%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f",
mean, maxVal, minVal, ptp, std, var, skew, kurt));
if (j < nFeatures - 1) {
sb.append(" ");
}
}
System.out.println(sb.toString());
}
}
import math
def main():
all_data = list(map(float, input().split()))
n_features = 19
n_samples = len(all_data) // n_features
results = []
for j in range(n_features):
col_data = [all_data[i * n_features + j] for i in range(n_samples)]
# 第一次遍历:计算总和、最小值、最大值
sum_val = sum(col_data)
max_val = -float('inf')
min_val = float('inf')
for val in col_data:
if val > max_val: max_val = val
if val < min_val: min_val = val
mean = sum_val / n_samples
ptp = max_val - min_val
# 第二次遍历:计算方差
sum_sq_diff = sum([(val - mean) ** 2 for val in col_data])
var = sum_sq_diff / n_samples
std = math.sqrt(var)
skew = 0.0
kurt = 0.0
# 第三次遍历:计算偏度和峰度
if std > 1e-9:
sum_cubed = sum([((val - mean) / std) ** 3 for val in col_data])
sum_quartic = sum([((val - mean) / std) ** 4 for val in col_data])
skew = sum_cubed / n_samples
kurt = sum_quartic / n_samples - 3.0
results.extend([mean, max_val, min_val, ptp, std, var, skew, kurt])
print(" ".join([f"{x:.2f}" for x in results]))
if __name__ == "__main__":
main()
算法及复杂度
- 算法:数据重组与统计计算
- 时间复杂度:
,其中
是输入的浮点数总数。我们需要读取所有数据,然后对每个特征列(共 19 列)进行常数次遍历(3 次),总计算量与数据点总数成正比。
- 空间复杂度:
,需要存储所有读入的浮点数以便进行多次计算。

京公网安备 11010502036488号