空间和时间的优化解决方案

问题描述

最近一位比我年长的开发人员给了我一个看似很小的 JavaScript 编程挑战。

它是这样的:

编写代码以在新数字插入跟踪器类时持续跟踪最高、最低和平均温度。

使用这些方法编写一个 TempTracker 类:

  • 一种插入新温度的方法
  • 一种获得迄今为止我们见过的最高温度的方法
  • 一种获得迄今为止我们见过的最低温度的方法
  • 一种获取迄今为止我们所见的所有温度平均值的方法

优化空间和时间。

以下是我的解决方案(您可以找到完整的源代码包括测试 here)。

class TempTracker {
    constructor() {
        this.temperatures = [];
    }

    all() {
        return [...this.temperatures];
    }

    clear() {
        this.temperatures.length = 0;
    }

    count() {
        return this.temperatures.length;
    }

    insert(temperature) {
        if (typeof temperature !== 'number' || Number.isNaN(temperature)) {
            throw new TypeError('must be a number');
        }

        this.temperatures.push(temperature);
    }

    add(temperature) {
        this.insert(temperature);
    }

    get length() {
        return this.count();
    }

    get lowest() {
        return this.check((temperatures) => Math.min(...temperatures));
    }

    get highest() {
        return this.check((temperatures) => Math.max(...temperatures));
    }

    get average() {
        return this.check((temperatures,length) => {
            const totalTemperature = temperatures.reduce(
                (acc,temperature) => acc + temperature,// eslint-disable-next-line
                0
            );

            return Number((totalTemperature / length).toFixed(2));
        });
    }

    // should be private method
    check(callback) {
        if (typeof callback !== 'function') {
            throw new TypeError('callback must be a function');
        }

        if (this.length === 0) {
            throw new Error('add at least one temperature value');
        }

        return callback(this.temperatures,this.length);
    }
}

虽然代码确实按预期工作,但我被告知我的代码没有针对空间和时间进行优化,因为随着输入增长到数百万或数十亿的温度,用于处理的内存将耗尽,并且还提到了其他一些内容的行,需要线性时间 O(?).

我对数据结构和算法的了解充其量是非常模糊的,我真的在努力改进这方面。

当我问我可以做些什么来改进代码时,我被告知可以使用数组以外的其他东西来存储温度列表,然后让我思考哪个对这个用例最有意义。

在 JavaScript 中可用的数据结构(至少我知道)中,我唯一能想到的是 SetsFloat32Arrays

我能否获得关于哪个更好以及为什么更好的指导,以及如何改进我的解决方案以“优化空间和时间”

解决方法

此任务不需要任何复杂的数据结构,您只需要跟踪:

  • 迄今为止所见的最高温度
  • 迄今为止所见的最低温度
  • 目前看到的温度总和
  • 到目前为止看到的温度数

这需要 O(1) 空间,并且每个所述操作需要 O(1) 时间(要获得平均值,将温度总和除以温度数量)。

,

对于给定的要求,您实际上并不需要存储所有单独的温度……不需要使用 all 方法。

你实际上只需要维护最小值、最大值、总和和计数。有了这 4 个数字,您就可以完成所需的一切:

class TempTracker {
    constructor() {
        this._low = Infinity;
        this._high = -Infinity;
        this._count = 0;
        this._sum = 0;
    }

    insert(temperature) {
        if (typeof temperature !== 'number' || Number.isNaN(temperature)) {
            throw new TypeError('must be a number');
        }
        this._low = Math.min(temperature,this._low);
        this._high = Math.max(temperature,this._high);
        this._count++;
        this._sum += temperature;
    }

    get lowest() {
        if (!this._count) throw new Error("no data");
        return this._low;
    }

    get highest() {
        if (!this._count) throw new Error("no data");
        return this._high;
    }

    get average() {
        if (!this._count) throw new Error("no data");
        return Math.round(this._sum * 100 / this._count) / 100;
    }
}