← 返回编程题库
coding-online-mean-mad简单免费版2000ms未尝试

滚动均值与平均绝对偏差

Running Mean and Mean Absolute Deviation

开始编码

某个流式统计服务接收一组数值样本,需要报告两个汇总量:算术 均值,以及 以均值为中心的平均绝对偏差(MAD),其定义为 MAD = mean(|x_i - mean(x)|)。均值是天然的位置估计量,MAD 是它的 L1 偏差搭档——最简单的不加权离散度度量,不对残差取平方。问题在于 MAD 依赖均值,而均值要等所有样本看完才能确定,因此严格意义上的单遍精确 MAD 是不可能的。标准做法是两遍:一遍算均值,第二遍累加绝对偏差。

实现 solution(values: list[float]) -> dict,返回 {"n": N, "mean": mean, "mad": MAD}。第一遍:mean = sum(values) / N。第二遍:MAD = sum(|x - mean| for x in values) / N。因为输入是具体的列表,O(N) 内存可接受——直接对列表迭代两次,只需两个标量累加器。

mean=1Ni=1Nxi,MAD=1Ni=1Nximean \text{mean} = \frac{1}{N}\sum_{i=1}^{N} x_i, \qquad \text{MAD} = \frac{1}{N}\sum_{i=1}^{N} \bigl|x_i - \text{mean}\bigr|

举例:solution([1.0, 2.0, 3.0, 4.0, 5.0]) 返回 {"n": 5, "mean": 3.0, "mad": 1.2}:均值 15/5 = 3.0,绝对偏差 [2, 1, 0, 1, 2],平均 6/5 = 1.2。再看一例:solution([7.0, 7.0, 7.0, 7.0]) 返回 {"n": 4, "mean": 7.0, "mad": 0.0}——所有偏差为 0。第三例:solution([]) 按约定返回 {"n": 0, "mean": 0.0, "mad": 0.0}

实践背景

均值与平均绝对偏差是任何时序监控仪表盘上的主力组合:延迟、成交率、单笔 P&L、滑点。它们计算便宜、读起来直观,而且单位正确(MAD 与原始数据同单位,这一点优于方差)。均值版 MAD 是与算术均值配套的通用离散度估计量——它是标准差的 L1 类比,在肥尾不是主要威胁、且希望度量保持原始单位(不取平方根)时,优先于标准差。它与 coding-mad-zscore-cross-section 中用于 1.4826 * MAD 重缩放的中位数版 MAD 不是同一个东西:那个版本是与中位数配套的稳健离散度估计量,一旦样本里出现离群值,两个公式给出的结果就会显著分叉。选哪一个是建模决策,不是编码决策——下面的实现是有意为之的均值版。

约束条件

  • 0 ≤ `N = len(values)` ≤ 10^5
  • 每个元素都是有限浮点数
  • `N == 0` → `{"n": 0, "mean": 0.0, "mad": 0.0}`
  • `N == 1` → `{"n": 1, "mean": values[0], "mad": 0.0}`
  • 输出键恰好为 `n`、`mean`、`mad`;类型分别是 `int`、`float`、`float`
  • 浮点比较容差 `rel_tol = 1e-9`、`abs_tol = 1e-12`

样例

Case 1 · statement-example: 1..5 has mean 3 and mean-MAD 1.2

输入: [[1,2,3,4,5]]

期望: {"n":5,"mean":3,"mad":1.2}

均值 = 15/5 = 3;绝对偏差 [2,1,0,1,2],其均值 6/5 = 1.2 即均值-MAD。

Case 2 · statement-example: all-equal gives MAD = 0

输入: [[7,7,7,7]]

期望: {"n":4,"mean":7,"mad":0}

所有元素相等,均值即元素值,所有偏差均为 0,故 MAD = 0。

Case 3 · statement-example: empty input returns zeros

输入: [[]]

期望: {"n":0,"mean":0,"mad":0}

空输入按约定返回 n=0、mean=0.0、mad=0.0。

Case 4 · boundary: single element has MAD = 0

输入: [[3.5]]

期望: {"n":1,"mean":3.5,"mad":0}

N=1 时均值即该元素值,与自身的绝对偏差为 0,故 MAD = 0。

Case 5 · typical: symmetric mix around zero

输入: [[-2,-1,0,1,2]]

期望: {"n":5,"mean":0,"mad":1.2}

对称样本,均值为 0;偏差等于绝对值 [2,1,0,1,2],平均得 1.2。

Case 6 · adversarial: single outlier inflates mean and mean-based MAD

输入: [[1,2,3,4,1000]]

期望: {"n":5,"mean":202,"mad":319.2}

均值-MAD 与均值一样对离群值敏感:一个 1000 把均值抬到 202,所有偏差都被放大,MAD = 319.2。这正是题面里强调的 mean-based 与 median-based 的差别——median-based MAD 在同一输入上几乎不动。

最近提交

还没有提交记录。

编码区

实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。

加载编辑器...
计时0:00

默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。

Case 1 · statement-example: 1..5 has mean 3 and mean-MAD 1.2

输入: [[1,2,3,4,5]]

期望: {"n":5,"mean":3,"mad":1.2}

均值 = 15/5 = 3;绝对偏差 [2,1,0,1,2],其均值 6/5 = 1.2 即均值-MAD。

Case 2 · statement-example: all-equal gives MAD = 0

输入: [[7,7,7,7]]

期望: {"n":4,"mean":7,"mad":0}

所有元素相等,均值即元素值,所有偏差均为 0,故 MAD = 0。

Case 3 · statement-example: empty input returns zeros

输入: [[]]

期望: {"n":0,"mean":0,"mad":0}

空输入按约定返回 n=0、mean=0.0、mad=0.0。

Case 4 · boundary: single element has MAD = 0

输入: [[3.5]]

期望: {"n":1,"mean":3.5,"mad":0}

N=1 时均值即该元素值,与自身的绝对偏差为 0,故 MAD = 0。

Case 5 · typical: symmetric mix around zero

输入: [[-2,-1,0,1,2]]

期望: {"n":5,"mean":0,"mad":1.2}

对称样本,均值为 0;偏差等于绝对值 [2,1,0,1,2],平均得 1.2。

Case 6 · adversarial: single outlier inflates mean and mean-based MAD

输入: [[1,2,3,4,1000]]

期望: {"n":5,"mean":202,"mad":319.2}

均值-MAD 与均值一样对离群值敏感:一个 1000 把均值抬到 202,所有偏差都被放大,MAD = 319.2。这正是题面里强调的 mean-based 与 median-based 的差别——median-based MAD 在同一输入上几乎不动。