C++ 中的滑動視窗中位數


假設我們有一列數字,並且有一個視窗大小 k,我們需要使用滑動視窗的方式找到中位數列表。因此,如果分佈如下所示:

視窗位置中位數
13-1-353681
13-1-35368-1
13-1-35368-1
13-1-353683
13-1-353685
13-1-353686

這裡我們假設 k 為 3,結果將是 [1,-1,-1,3,5,6]

為了解決這個問題,我們將遵循以下步驟:

  • 定義一個集合 arr
  • 定義一個函式 insert(),它將接收 x,
  • 將 x 插入到 arr 中
  • 定義一個函式 delete_(),它將接收 x,
  • 從 arr 中刪除 x,如果存在
  • 定義一個函式 getMedian()
  • n := arr 的大小
  • a := 從 arr 的第一個元素開始向前跳躍 n/2 – 1 步,並獲取其值
  • b := 從 arr 的第一個元素開始向前跳躍 n/2 步,並獲取其值
  • 如果 arr 的大小為,則:
    • 返回 b
  • 返回 (a + b) * 0.5
  • 從主方法執行以下操作
  • 定義一個數組 ans
  • 清空陣列 arr
  • 初始化 i := 0,當 i < k 時,更新(i 增加 1),執行:
    • 呼叫函式 insert(nums[i])
  • 初始化 i := k,j := 0,當 i < nums 的大小,更新(i 增加 1),(j 增加 1),執行:
    • 將 getMedian() 的返回值插入到 ans 的末尾
    • 呼叫函式 delete_(nums[j])
    • 呼叫函式 insert(nums[i])
  • 將 getMedian() 的返回值插入到 ans 的末尾
  • 返回 ans

讓我們看看下面的實現來更好地理解:

示例

 現場演示

#include <bits/stdc++.h>
using namespace std;
void print_vector(vector<auto> v){
   cout << "[";
   for(int i = 0; i<v.size(); i++){
      cout << v[i] << ", ";
   }
   cout << "]"<<endl;
}
class Solution {
public:
   multiset <double> arr;
   void insert(double x){
      arr.insert(x);
   }
   void delete_(double x){
      arr.erase(arr.find(x));
   }
   double getMedian(){
      int n = arr.size();
      double a = *next(arr.begin(), n / 2 - 1);
      double b = *next(arr.begin(), n / 2);
      if(arr.size() & 1)return b;
      return (a + b) * 0.5;
   }
   vector<double> medianSlidingWindow(vector<int>& nums, int k) {
      vector <double> ans;
      arr.clear();
      for(int i = 0; i < k; i++){
         insert(nums[i]);
      }
      for(int i = k, j = 0; i < nums.size(); i++, j++){
         ans.push_back(getMedian());
         delete_(nums[j]);
         insert(nums[i]);
      }
      ans.push_back(getMedian());
      return ans;
   }
};
main(){
   Solution ob;
   vector<int> v = {1,3,-1,-3,5,3,6,8};
   print_vector(ob.medianSlidingWindow(v, 3));
}

輸入

{1,3,-1,-3,5,3,6,8}

輸出

[1, -1, -1, 3, 5, 6, ]

更新於: 2020年6月1日

1K+ 次檢視

開啟你的 職業生涯

透過完成課程獲得認證

開始
廣告