滑動視窗中位數

2022-06-05 19:03:07 字數 1940 閱讀 3079

中位數是有序序列最中間的那個數。如果序列的長度是偶數,則沒有最中間的數;此時中位數是最中間的兩個數的平均數。

例如:給你乙個陣列 nums,有乙個長度為 k 的視窗從最左端滑動到最右端。視窗中有 k 個數,每次視窗向右移動 1 位。你的任務是找出每次視窗移動後得到的新視窗中元素的中位數,並輸出由它們組成的陣列。

給出 nums = [1,3,-1,-3,5,3,6,7],以及 k = 3。

視窗位置                      中位數

--------------- -----

[1 3 -1] -3 5 3 6 7 1

1 [3 -1 -3] 5 3 6 7 -1

1 3 [-1 -3 5] 3 6 7 -1

1 3 -1 [-3 5 3] 6 7 3

1 3 -1 -3 [5 3 6] 7 5

1 3 -1 -3 5 [3 6 7] 6

因此,返回該滑動視窗的中位數陣列 [1,-1,-1,3,5,6]。

【思路】

看到計算中位數,首先想到的是。將較小的半部分放在大頂堆中,較大的部分放在小頂堆中,並且滿足「小頂堆大小」與「大頂堆大小」的平衡關係,即可很方便的取得中位數。順著這個思路我們需要做的是:

提供大頂堆和小頂堆;

新增資料,並且要平衡大小頂堆的大小;

刪除資料,並且要平衡大小頂堆的大小;

獲取中位數,本題中也就是根據滑動視窗大小取堆頂元素(視窗大小為奇數,則中位數為小頂堆堆頂;為偶數,則取兩堆頂的平均值)。

現在問題又來了,從堆中刪除指定資料是件麻煩的事,堆結構只能刪除堆頂元素。

記錄待刪除元素的待刪除次數;

需要有兩個值分別記錄兩個堆中的有效資料個數;

如何確保堆頂元素有效:

新增資料不會影響堆頂元素的有效性;

刪除堆中資料可能影響到堆頂元素的有效性(包括刪除視窗最左側值、調整堆大小時的刪除操作)。

總結思路+雜湊表

提供大小堆資料結構,並記錄各堆中的有效資料個數;

延遲刪除,記錄待刪除元素的待刪除次數(雜湊表);

要平衡大小堆,保證大小堆的有效元素個數關係;

保證堆頂元素有效性,在堆的的刪除操作後清除無效的堆頂元素;

提供 新增元素、刪除元素、獲取中位數 的介面。

class maxminheap 

} else if (maxheapnums < minheapnums) }}

public:

maxminheap(int k) : n(k), maxheapnums(0), minheapnums(0)

// 新增元素

void add(int value) else

// 調整大小堆元素比例

adjust();

}// 刪除元素

void del(int value)

} else

}// 調整大小堆元素比例

adjust();

}// 獲取中位數

double getmedian()

};class solution

// 移動滑動視窗 [left, right)

vectorans(1, window.getmedian());

for (int left = 0, right = k; right < nums.size(); ++left, ++right)

return ans;

}};

480 滑動視窗中位數

題目描述 中位數是有序序列最中間的那個數。如果序列的大小是偶數,則沒有最中間的數 此時中位數是最中間的兩個數的平均數。例如 2,3,4 中位數是 3 2,3 中位數是 2 3 2 2.5 給你乙個陣列 nums,有乙個大小為 k 的視窗從最左端滑動到最右端。視窗中有 k 個數,每次視窗向右移動 1 ...

480 滑動視窗中位數

中位數是有序序列最中間的那個數。如果序列的長度是偶數,則沒有最中間的數 此時中位數是最中間的兩個數的平均數。例如 2,3,4 中位數是 3 2,3 中位數是 2 3 2 2.5 給你乙個陣列 nums,有乙個長度為 k 的視窗從最左端滑動到最右端。視窗中有 k 個數,每次視窗向右移動 1 位。你的任...

LeetCode 滑動視窗中位數

q 中位數是有序序列最中間的那個數。如果序列的大小是偶數,則沒有最中間的數 此時中位數是最中間的兩個數的平均數。例如 2,3,4 中位數是 3 2,3 中位數是 2 3 2 2.5 給你乙個陣列 nums,有乙個大小為 k 的視窗從最左端滑動到最右端。視窗中有 k 個數,每次視窗向右移動 1 位。你...