演算法 動態中位數問題

2021-08-18 22:02:19 字數 3194 閱讀 2800

輸入一組整數a1, a2, …, an ,每輸入乙個整數,輸出到此時為止的中位數。

中位數定義:如果數串的大小是偶數 2j,中位數是從小到大排列的第 j 個數;如果數串的大小是奇數 2j+1,中位數是從小到大排列的第 j+1 個數。

一組整數,數字和數字之間以空格隔開。

一組整數,數字和數字之間以空格隔開。最後乙個數後面也有空格。

第 i 個輸出的整數,是前 i 個輸入的中位數。

-18 -2 14 -20 -6 7 2 14 11 6

-18 -18 -2 -18 -6 -6 -2 -2 2 2

時間複雜度請不要超過o(nlogn)。

本演算法可以利用堆的結構來動態的求解乙個數串的中位數。因為該題目要求動態的輸入當前串的中位數。通過使用堆結構,通過維護乙個大根堆和乙個小根堆和乙個中位數middle。構建堆只需要o(n)時間複雜度,而提取中位數則只需要線性時間複雜度o(1)。

該演算法將是高效的,但是在具體實現的過程中,特別是動態加入數串的過程中要平衡兩個堆之間元素個數已確保middle是已經輸入數串的中位數。具體而言:

(1)、當最大根堆元素個數大於最小根堆元素個數時,彈出最大根堆堆頂元素給middle,原middle元素入最小根堆。

(2)、當最小根堆元素個數-最小根堆元素個數》=2時,彈出最小根堆堆頂元素給middle,原middle元素入最大根堆。

#include 

#include

#include

using

namespace

std;

void fix_min_heap(long *, long fix_num, long num); //修復小根堆的函式

void fix_max_heap(long *, long fix_num, long num); //修復大根堆的函式

void fix_min_heap_up(long *, long up);//從底部向上修復最小根堆

void fix_max_heap_up(long *, long up);//從底部向上修復最大根堆

int main(void)

}else

new_ptr[0] = 0;

for(long i =1; i <= right_size ; ++i)

free(min_vec);

min_vec = new_ptr;

}min_vec[right_size] = a;

fix_min_heap_up(min_vec, right_size);

if((right_size - left_size) >= 2)

new_ptr[0] = 0;

for(long i =1; i <= left_size ; ++i)

free(max_vec);

max_vec = new_ptr;

}max_vec[left_size] = middle;

fix_max_heap_up(max_vec, left_size);//進行最大根堆的修復

middle = min_vec[1];//將最小根堆的堆頂作為middle

min_vec[1] = min_vec[right_size];

min_vec[right_size] = 0;

right_size--;

fix_min_heap(min_vec, 1, right_size);

}}else

new_ptr[0] = 0;

for(long i =1; i <= left_size ; ++i)

free(max_vec);

max_vec = new_ptr;

}max_vec[left_size] = a;

fix_max_heap_up(max_vec , left_size);

if((left_size - right_size) >= 1)

new_ptr[0] = 0;

for(long i =1; i <= right_size ; ++i)

free(min_vec);

min_vec = new_ptr;

}min_vec[right_size] = middle;

fix_min_heap_up(min_vec, right_size);

middle = max_vec[1];

//進行最大根修復

max_vec[1] = max_vec[left_size];

max_vec[left_size] = 0;

left_size--;

fix_max_heap(max_vec, 1, left_size);}}

}printf("%ld ", middle);

a = 0;

}free(min_vec);

min_vec = null;

free(max_vec);

max_vec = null;

return0;}

//構造小根堆

void fix_min_heap(long *p, long fix_num, long num)

if(fix_num * 2+1

<= num && p[fix_num * 2 + 1] < temp&& p[fix_num * 2 + 1] < left)

if(next != fix_num)else

}}//構造大根堆

void fix_max_heap(long * p, long fix_num, long num)

if(fix_num * 2+1

<= num && p[fix_num * 2 + 1] > temp&& p[fix_num * 2 + 1] > left)

if(next != fix_num)else

}}void fix_min_heap_up(long *p, long up)//從底部向上修復最小根堆

if( next == up)

break;

}up = next;

}}void fix_max_heap_up(long *p, long up)//從底部向上修復最大根堆

if( next == up)

break;

}up = next;

}}

動態中位數

178.動態中位數 統計描述 提交自定義測試 題目描述 輸入n個32位有符號整數,當已輸入的個數為奇數個時,輸出此時的中位數。輸入描述 第一行乙個整數n 第二行n個32位有符號整數。輸出描述 輸出一行,n 2 上取整 個中位數,中間用空格隔開。對於 40 資料 n 1000 對於所有資料 n 100...

動態中位數

依次讀入乙個整數序列,每當已經讀入的整數個數為奇數時,輸出已讀入的整數構成的序列的中位數。輸入格式 第一行輸入乙個整數p,代表後面資料集的個數,接下來若干行輸入各個資料集。每個資料集的第一行首先輸入乙個代表資料集的編號的整數。然後輸入乙個整數m,代表資料集中包含資料的個數,m一定為奇數,資料之間用空...

動態中位數

題意 注 本文的 中的輸出不嚴格正確,反正loj的資料也沒多強,不會pe。如果後面加強了當我沒說 沒錯,第乙個還是我的做法。記得是哪年的scp還是noip初賽竟然程式題就是這個思路,然後我照搬了。我們這道題目反著考慮,它讓我們加數,我們就刪除數字,從後往前刪除數字,我們先建乙個排好序的鍊錶,然後從中...