輸入一組整數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初賽竟然程式題就是這個思路,然後我照搬了。我們這道題目反著考慮,它讓我們加數,我們就刪除數字,從後往前刪除數字,我們先建乙個排好序的鍊錶,然後從中...