mode_sorted.js

/**
 * [众数](https://en.wikipedia.org/wiki/Mode_%28statistics%29)是数据集中出现次数最多的数值。
 * 一个数据集可能存在多个众数:当出现频率相同的多个值时,本算法将返回最后出现的众数。
 * 这是[集中趋势的度量](https://en.wikipedia.org/wiki/Central_tendency)方法:
 * 用于寻找数据集的典型值或中心值。
 *
 * 由于输入已排序,算法时间复杂度为`O(n)`。
 *
 * @param {Array<number>} sorted 已排序的数据样本(需包含至少一个数据点)
 * @returns {number} 众数值
 * @throws {Error} 当输入为空时抛出错误
 * @example
 * modeSorted([0, 0, 1]); // => 0
 */
function modeSorted(sorted) {
    // 处理边界情况:
    // 空数组无众数定义
    if (sorted.length === 0) {
        throw new Error("计算众数需要至少一个数据点");
    }
    if (sorted.length === 1) {
        return sorted[0];
    }

    // 以下逻辑处理数组长度>1的情况,因此从索引1开始遍历
    let last = sorted[0];
    // 当前找到的众数值
    let value = Number.NaN;
    // 当前众数出现次数
    let maxSeen = 0;
    // 当前数值连续出现次数
    let seenThis = 1;

    // 遍历至sorted.length + 1以处理众数是最大元素的情况,
    // 最后一步将比较sorted[i](此时为undefined)与最后一个元素
    for (let i = 1; i < sorted.length + 1; i++) {
        // 发现新数值时进行判断
        if (sorted[i] !== last) {
            // 若当前数值出现次数超过已知众数,则更新众数值
            if (seenThis > maxSeen) {
                maxSeen = seenThis;
                value = last;
            }
            seenThis = 1;
            last = sorted[i];
            // 相同数值则累加计数器
        } else {
            seenThis++;
        }
    }
    return value;
}

export default modeSorted;