统计量列表
题意
给定一个整数序列 arr 和一组窗口大小 windows。对于每个位置,以公共右边界为基准,对每个窗口大小取右对齐的子数组,分别计算 5 个统计量(mean、std、min、max、slope),然后按窗口顺序拼接成一行输出。
具体规则:
- 公共右边界
,窗口
取
- 总行数
,若
输出
[] - std:样本标准差(ddof=1),窗口为 1 时等于 0
- slope:最小二乘法斜率,
,窗口为 1 或分母为 0 时等于 0
- 数值格式:整数不带小数点;非整数最多 3 位小数,四舍五入,去掉末尾无意义的零
思路
这题没有什么算法上的难度,就是一道模拟题,但细节不少。你可以问自己几个问题来理清思路:
1. 窗口怎么对齐?
题目说"右对齐"——所有窗口共享同一个右边界 。大窗口的左边界更靠左,小窗口更靠右。第
行的
。
拿样例 [2, 4, 6, 8, 10, 12], [2, 4] 来说,,第 0 行
:
:取
arr[2..3]=[6, 8]:取
arr[0..3]=[2, 4, 6, 8]
2. slope 怎么算?
标准最小二乘线性回归斜率。横坐标固定为 ,纵坐标是子数组的元素。公式:
$$
其中 。
3. 数值格式怎么处理?
这是最容易出错的地方。规则是:
- 如果结果恰好是整数(比如
7.0),输出7 - 否则保留最多 3 位小数,去掉末尾的零(
1.100→1.1,2.582保持不变)
Python 里可以先用 f"{x:.3f}",然后 rstrip('0').rstrip('.'),再判断是否为整数做特殊处理。
4. 整体流程?
对每行输入:
- 解析
arr和windows - 计算
max_w和行数n - 对每一行,算出右边界
,对每个窗口切片,算 5 个统计量,拼接输出
时间复杂度 ,其中
是窗口数量,
是窗口大小,完全没有性能压力。
代码
import sys
from math import sqrt
def format_num(x):
if x == int(x):
return str(int(x))
s = f"{x:.3f}"
s = s.rstrip('0').rstrip('.')
return s
def compute_stats(sub):
w = len(sub)
mean = sum(sub) / w
if w == 1:
std = 0
else:
variance = sum((v - mean) ** 2 for v in sub) / (w - 1)
std = sqrt(variance)
mn = min(sub)
mx = max(sub)
if w == 1:
slope = 0
else:
x_mean = (w - 1) / 2.0
num = sum(i * sub[i] for i in range(w)) - w * x_mean * mean
den = sum(i * i for i in range(w)) - w * x_mean * x_mean
slope = num / den if abs(den) > 1e-12 else 0
return [mean, std, mn, mx, slope]
for line in sys.stdin:
line = line.strip()
if not line:
continue
parts = line.split('],')
arr = list(map(int, parts[0].strip().strip('[').split(',')))
windows = list(map(int, parts[1].strip().strip('[] ').split(',')))
max_w = max(windows)
n = len(arr) - max_w + 1
if n <= 0:
print("[]")
continue
for i in range(n):
R = i + max_w - 1
row = []
for w in windows:
left = R - w + 1
row.extend(compute_stats(arr[left:R+1]))
print("[" + ", ".join(format_num(v) for v in row) + "]")
#include <bits/stdc++.h>
using namespace std;
string formatNum(double x) {
if (abs(x - round(x)) < 1e-9) return to_string((long long)round(x));
char buf[64];
sprintf(buf, "%.3f", x);
string s(buf);
size_t dot = s.find('.');
if (dot != string::npos) {
size_t last = s.size() - 1;
while (last > dot && s[last] == '0') last--;
if (last == dot) last--;
s = s.substr(0, last + 1);
}
return s;
}
struct Stats { double mean, std_, mn, mx, slope; };
Stats computeStats(vector<int>& arr, int left, int right) {
int w = right - left + 1;
double sum = 0;
int mn = INT_MAX, mx = INT_MIN;
for (int i = left; i <= right; i++) {
sum += arr[i]; mn = min(mn, arr[i]); mx = max(mx, arr[i]);
}
double mean = sum / w;
double std_val = 0;
if (w > 1) {
double var = 0;
for (int i = left; i <= right; i++) { double d = arr[i] - mean; var += d * d; }
std_val = sqrt(var / (w - 1));
}
double slope = 0;
if (w > 1) {
double x_mean = (w - 1) / 2.0;
double num = 0, den = 0;
for (int i = 0; i < w; i++) { num += (double)i * arr[left + i]; den += (double)i * i; }
num -= w * x_mean * mean; den -= w * x_mean * x_mean;
if (abs(den) > 1e-12) slope = num / den;
}
return {mean, std_val, (double)mn, (double)mx, slope};
}
int main() {
string line;
while (getline(cin, line)) {
if (line.empty()) continue;
size_t p1 = line.find('['), p2 = line.find(']', p1);
size_t p3 = line.find('[', p2), p4 = line.find(']', p3);
string arrStr = line.substr(p1 + 1, p2 - p1 - 1);
string winStr = line.substr(p3 + 1, p4 - p3 - 1);
vector<int> arr, windows;
{ stringstream ss(arrStr); string t; while (getline(ss, t, ',')) arr.push_back(stoi(t)); }
{ stringstream ss(winStr); string t; while (getline(ss, t, ',')) windows.push_back(stoi(t)); }
int maxW = *max_element(windows.begin(), windows.end());
int n = (int)arr.size() - maxW + 1;
if (n <= 0) { cout << "[]" << endl; continue; }
for (int i = 0; i < n; i++) {
int R = i + maxW - 1;
vector<string> row;
for (int w : windows) {
int left = R - w + 1;
Stats s = computeStats(arr, left, R);
row.push_back(formatNum(s.mean));
row.push_back(formatNum(s.std_));
row.push_back(formatNum(s.mn));
row.push_back(formatNum(s.mx));
row.push_back(formatNum(s.slope));
}
cout << "[";
for (int j = 0; j < (int)row.size(); j++) { if (j) cout << ", "; cout << row[j]; }
cout << "]" << endl;
}
}
}

京公网安备 11010502036488号