Məsələnin həllini xətti massiv vasitəsilə modelləşdirək. Hər addımda daxil olan ədədləri onun içində sıralanmış şəkildə saxlayacağıq. Yeni elementin daxil ediləcəyi mövqeyi ikili axtarış vasitəsilə tapacağıq. Lakin daxiletmə əməliyyatının özü (məsələn, massiv verilənlər strukturu ilə həyata keçirilibsə) xətti zamanda yerinə yetirilir. Beləliklə, O(n^2) zaman mürəkkəbliyinə malik ümumi həll vaxt məhdudiyyətinə sığmayacaq.
İki qalaq (heap) elan edək: biri — minimumu saxlamaq üçün (-qalaq), digəri — maksimumu saxlamaq üçün (-qalaq). Onların işini elə təşkil edək ki, aşağıdakı şərtlər ödənsin:
-qalağın istənilən elementi -qalağın istənilən elementindən kiçik olsun (kiçik ədədlər -qalaqda, böyük ədədlər isə -qalaqda saxlanılır);
qalaqların ölçüləri bərabər olsun. Əgər ümumi element sayı tək olarsa, -qalaq -qalaqdan bir element çox saxlamalıdır.
Yeni element əlavə edildikdə, əgər o, -qalağın minimal elementindən kiçik deyilsə, onu -qalağa yerləşdiririk; əks halda — -qalağa. Bundan sonra yuxarıda qeyd olunan xüsusiyyətləri qorumaq üçün qalaqların balanslaşdırılmasını yerinə yetiririk:
Əgər -qalağın ölçüsü -qalağın ölçüsündən böyükdürsə, -qalağın ən böyük elementini -qalağa köçürürük.
Əgər -qalağın ölçüsü -qalağın ölçüsündən birdən çox böyükdürsə, -qalağın ən kiçik elementini -qalağa köçürürük.
Cari ardıcıllığın medianı aşağıdakı kimi müəyyən edilir:
əgər ədədlərin sayı tək olarsa, medianı -qalağın ən kiçik elementi təşkil edir;
əgər ədədlərin sayı cüt olarsa, median -qalağın ən kiçik elementi ilə -qalağın ən böyük elementinin ədədi ortasına bərabərdir.
Elementin qalağa daxil edilməsi və sonrakı balanslaşdırma O(log_2n) vaxtında yerinə yetirilir. Beləliklə, alqoritmin ümumi işləmə vaxtı O(nlog_2n) təşkil edir.
Misal
Ədədlərin ardıcıl daxil olması zamanı medianın hesablanması prosesinə baxaq. Aydınlıq üçün hər yeni ədəd əlavə edildikdən sonra ardıcıllığın nizamlandığını qəbul edəcəyik. Hər ardıcıllığın altında ona uyğun median dəyəri göstərilib.
Misaldakı bütün elementlər emal edildikdən sonra qalaqların vəziyyəti aşağıdakı kimi olacaq:
Elementlərin sayı tək olduğundan, median -qalağın ən kiçik elementinə, yəni -ə bərabərdir.
Tutaq ki, növbəti daxil olan ədəd -dir. O, -qalağın minimal elementindən kiçik olmadığı üçün onu -qalağa əlavə edirik. Bundan sonra -qalağın ölçüsü -qalağın ölçüsündən iki element çox olacaq, buna görə də balanslaşdırma yerinə yetirilməlidir: -qalağın ən kiçik elementini () -qalağa köçürürük. Başqa sözlə, -ü -qalaqdan silib -qalağa əlavə edirik.
İndi massivdəki elementlərin ümumi sayı cüt olduğundan, median -qalağın ən kiçik elementinin () və -qalağın ən böyük elementinin () ədədi ortası kimi müəyyən edilir, yəni (35 + 4) / 2 = 19. Məsələdə medianın yalnız tam hissəsini çıxarmaq tələb olunur.
Alqoritmin realizasiyası
-qalağı mMinHeap və -qalağı mMaxHeap elan edək.
priority_queue<int, vector<int>, greater<int> > mMinHeap;
priority_queue<int, vector<int>, less<int> > mMaxHeap;Qalaqları ilkin qiymətləndirək. dəyişənində daxil olan ədədlərin sayını saxlayacağıq. Rahatlıq üçün qalaqları fiktiv elementlərlə ilkin qiymətləndiririk.
mMaxHeap.push(-MAX); mMinHeap.push(MAX);
c = 1;Növbəti ədədi emal edirik.
while(scanf("%d",&n) == 1)
{ -in dəyərindən asılı olaraq onu qalaqlardan birinə yerləşdiririk.
if (n >= mMinHeap.top()) mMinHeap.push(n);
else mMaxHeap.push(n);Əgər -qalağın ölçüsü -qalağın ölçüsündən böyükdürsə və ya -qalağın ölçüsü -qalağın ölçüsündən birdən çox böyükdürsə, balanslaşdırma yerinə yetiririk.
if(mMaxHeap.size() > mMinHeap.size())
{ -qalağın ən böyük elementini -qalağa köçürürük.
mMinHeap.push(mMaxHeap.top());
mMaxHeap.pop();
} else
if(mMaxHeap.size() + 1 < mMinHeap.size())
{ -qalağın ən kiçik elementini -qalağa köçürürük.
mMaxHeap.push(mMinHeap.top());
mMinHeap.pop();
}Massivdəki elementlərin sayının cüt-təkliyindən asılı olaraq medianın dəyərini çap edirik.
if (c % 2) printf("%d\n",mMinHeap.top());
else printf("%d\n",(mMinHeap.top() + mMaxHeap.top())/2);
c++;
}