[C/C++] 剣はオファー II 041 を指します。スライディング ウィンドウの平均値

一緒に創造し、成長するために一緒に働きましょう!「ナゲッツデイリー新プラン・8月アップデートチャレンジ」参加26日目、イベント詳細はこちら


トピック リンク:剣はオファー II 041 を指します。スライディング ウィンドウの平均値

トピックの説明

整数のストリームとウィンドウ サイズを指定して、スライディング ウィンドウのサイズに基づいて、スライディング ウィンドウ内のすべての数値の平均を計算します。

実装MovingAverageクラス:

  • MovingAverage(int size)ウィンドウ サイズでオブジェクトをsize初期化。
  • double next(int val) メンバー関数next が呼び出されるたびに、スライディング ウィンドウに整数が追加されます。データ ストリームのsize最後の。

ヒント:

  • 1 s 1000 1 \leqslant サイズ \leqslant 1000
  • 1 0 5   a l 1 0 5 -10^5 \leqslant val \leqslant 10^5
  • ほとんどの呼び出し next 方法  1 0 4 10^4  回

例 1:

输入:
inputs = ["MovingAverage", "next", "next", "next", "next"]
inputs = [[3], [1], [10], [3], [5]]
输出:
[null, 1.0, 5.5, 4.66667, 6.0]

解释:
MovingAverage movingAverage = new MovingAverage(3);
movingAverage.next(1); // 返回 1.0 = 1 / 1
movingAverage.next(10); // 返回 5.5 = (1 + 10) / 2
movingAverage.next(3); // 返回 4.66667 = (1 + 10 + 3) / 3
movingAverage.next(5); // 返回 6.0 = (10 + 3 + 5) / 3
复制代码

質問の意味を整理する

この問題には、スライディング ウィンドウとデータ ストリームのサイズが与えられ、毎回整数が与えられ、整数がスライディング ウィンドウに入れられ、スライディング ウィンドウ内の整数の平均がカウントされます。スライディング ウィンドウがいっぱいになると、FIFO ルールが満たされます。

問題解決分析

由于题目规定滑动窗口中的数据满足先进先出规则,我们可以使用 队列 来模拟实现这一过程,用一个变量记录队列中所有元素的总和,当队列中的元素超过滑动窗口大小时将队头元素弹出,并维护此时队列元素中所有元素的和。每次返回队列中所有元素的平均值即可。

具体实现

  1. 记录滑动窗口大小,初始化队列。
  2. 将给定数据压入队列,并判断队列中元素个数是否超过滑动窗口大小。
  3. 当超过滑动窗口大小时从队头进行弹出元素,并且不断维护队列中元素的总和。
  4. 返回队列元素总和除以队列中的元素个数即得滑动窗口中元素的平均值。

复杂度分析

  • 时间复杂度:初始化和每次调用 next 的时间复杂度都是  ( 1 ) O(1)
  • 空间复杂度: ( s ) O(size) ,其中 size 是滑动窗口的大小。空间复杂度主要取决于队列,队列中的数字个数不超过 size

代码实现

class MovingAverage {
private:
    queue<int> que;
    int n;
    double sum;
public:
    /** Initialize your data structure here. */
    MovingAverage(int size) {
        //记录滑动窗口大小
        n = size;
        //sum记录队列中元素总和
        sum = 0;
        //清空队列
        while(que.size()) que.pop();
    }
    
    double next(int val) {
        //维护队列中元素总和
        sum += val;
        que.push(val);
        //维护队列中的元素个数不超过滑动窗口大小
        while(que.size() > n){
            sum -= que.front();
            que.pop();
        }
        //返回平均值
        return sum / (double)que.size();
    }
};

/**
 * Your MovingAverage object will be instantiated and called as such:
 * MovingAverage* obj = new MovingAverage(size);
 * double param_1 = obj->next(val);
 */
复制代码

总结

  • 该题的核心在于理解题意,其次在于对 队列 数据结构的运用。
  • 计算队列中所有元素和可以使用一个变量进行记录,通过维护队列总所有元素总和,可以 O(1) 进行计算队列中所有元素的平均值。
  • 测试结果:

ソードフィンガー041.png

结束语

学习对一个人的重要性,不只在于习得新知识,更在于帮助我们保持思考的习惯,继而不断成长。让学习成为一种习惯,你所收获的,将会是应对生活的底气和智慧。新的一天,加油!

おすすめ

転載: juejin.im/post/7134176329804562462