中位數是有序序列最中間的那個數。如果序列的長度是偶數,則沒有最中間的數;此時中位數是最中間的兩個數的平均數。【思路】例如:給你乙個陣列 nums,有乙個長度為 k 的視窗從最左端滑動到最右端。視窗中有 k 個數,每次視窗向右移動 1 位。你的任務是找出每次視窗移動後得到的新視窗中元素的中位數,並輸出由它們組成的陣列。
給出 nums = [1,3,-1,-3,5,3,6,7],以及 k = 3。
因此,返回該滑動視窗的中位數陣列 [1,-1,-1,3,5,6]。視窗位置 中位數
--------------- -----
[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
看到計算中位數,首先想到的是堆。將較小的半部分放在大頂堆中,較大的部分放在小頂堆中,並且滿足「小頂堆大小」與「大頂堆大小」的平衡關係,即可很方便的取得中位數。順著這個思路我們需要做的是:
提供大頂堆和小頂堆;
新增資料,並且要平衡大小頂堆的大小;
刪除資料,並且要平衡大小頂堆的大小;
獲取中位數,本題中也就是根據滑動視窗大小取堆頂元素(視窗大小為奇數,則中位數為小頂堆堆頂;為偶數,則取兩堆頂的平均值)。
現在問題又來了,從堆中刪除指定資料是件麻煩的事,堆結構只能刪除堆頂元素。
記錄待刪除元素的待刪除次數;
需要有兩個值分別記錄兩個堆中的有效資料個數;
如何確保堆頂元素有效:
新增資料不會影響堆頂元素的有效性;
刪除堆中資料可能影響到堆頂元素的有效性(包括刪除視窗最左側值、調整堆大小時的刪除操作)。
【總結思路】堆+雜湊表
提供大小堆資料結構,並記錄各堆中的有效資料個數;
延遲刪除,記錄待刪除元素的待刪除次數(雜湊表);
要平衡大小堆,保證大小堆的有效元素個數關係;
保證堆頂元素有效性,在堆的的刪除操作後清除無效的堆頂元素;
提供 新增元素、刪除元素、獲取中位數 的介面。
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 位。你...