מבני נתונים ואלגוריתמים - מחברת קורס/אלגוריתמים/מיון הכנסה ומיזוג/תרגילים/מציאת איבר הרוב במערך/תשובה
פרק זה לוקה בחסר. אתם מוזמנים לתרום לוויקיספר ולהשלים אותו. ראו פירוט בדף השיחה.
א
[עריכה]ראשית נמיין את Aבעזרת אלגוריתם מיון הרץ בזמן ) . O(n log nבפרט ניתן להשתמש במיון מיזוג. לאחר המיון, המופעים של כל מספר מופיעים ברצף. בפרט, אם יש איבר רוב אזי הוא מופיע ממקום ועד מקום כאשר \left\lfloor n / 2 \rightt\rfloor ואם אין איבר רוב אזי מספר המופעים של כל איבר הוא לכל היותר .n/2בנקודה זו ישנן מספר אופציות:
- נרוץ על אברי המערך לפי הסדר ונספור הופעות רצופות של כל איבר. אם מספר ההופעות הרצופות של איבר כלשהו הוא לפחות 1+ -n/2אז הוא איבר הרוב. אחרת, אין איבר כזה.
- נרוץ על iמ 1 ועד )לכל היותר( , n n / 2 n / 2ונבדוק אם ] . A[i ] A[i n / 2אם מצאנו כזה iאז נחזיר את ] ) A[iאחרת נחזיר שאין איבר רוב(.
- נשים לב כי לאחר מיון המערך, אם יש בו איבר רוב אזי הוא בהכרח נמצא במקום 1+ .n/2נימוק :
האינדקס הראשון של איבר הרוב חייב להתחיל ב iכך ש מצד אחד 1 i ומצד שני 1 i n n / 2 n / 2 n / 2 ולכן תמיד מתקיים: . i n / 2 1 i n / 2מספיק אם כן לבדוק האם ]1 A[ n / 2 מופיע לפחות 1+ n/2פעמים וזאת ע"י ספירת האיברים השווים לאיבר זה והנמצאים משמאלו או מימינו במערך. זמן הריצה בכל מקרה: זמן הריצה של אלגוריתם המיון ועוד לולאה העוברת על כל איבר במערך לכל היותר פעם אחת - ). (n log n) (n) (n log n להלן הפסאודו קוד עבור האופציה הראשונה.
)Maj(n,A
/* Merge-Sort(A) /* Sort the elements of A /* j1; xA[1]; count 1 /* x is the current candidate for the majority element { ) while (j < n and count n/2 ;++j 1+if (A[j]=x) count count /* if the next element is the same as the candidate /* (previous element) then increase count { else ;]x A[j /* /* change candidate to new element and initialize count 1 count } )if (count > n/2) return(x )else return(No-Majority-Element }
ב
[עריכה]האלגוריתם ראשית קורא ל , Candidateהמחזירה לו "מועמד" .xלאחר מכן עובר האלגוריתם על איברי המערך Aוסופר כמה פעמים הופיע .xאם מספר זה הוא לפחות 1 n / 2 אזי הוא מחזיר אותו,
ואחרת הוא מחזיר שאין איבר רוב. לפי ההנחה על ,Candidateאם יש במערך איבר רוב אזי השגרה מחזירה אותו, ובמצב זה האלגוריתם יחזיר אותו. אם אין איבר רוב אזי לא משנה מה מחזירה ,Candidateהאיבר המוחזר יופיע לכל היותר n / 2פעמים ולכן האלגוריתם יחזיר שאין איבר רוב, כנדרש. זמן הריצה הוא פשוט הסכום של זמן הריצה של ,Candidateוהלולאה שעוברת פעם אחת על ,Aכלומר ).T(n)+O(n
)Maj(A,n
/* x Candidate(A,n) /* x is the candidate for being a majority element 0 count )for (j=1 to n /* /* count number of appearances of x in A if (A[j]==x) then 1+count count /* if(count n/2 +1) then return(x) /* x is the majority element )else return(NO-MAJORITY-ELEMENT n 2 n
ג
[עריכה]ראשית נשים לב כי yהוא איבר רוב ב Bאם ורק אם הוא מופיע לפחות 1
2 2 פעמים ב .Bיהי xאיבר הרוב ב .Aישנם שלושה מקרים: )1( גם A[i] ≠ xוגם (2) ;A[j] ≠ x A[i]=xו A[i] ≠ x (3) ; A[j]xו ;A[j]=xבמקרה הראשון, מספר המופעים של xב Bשווה לזה שב ,Aכלומר הוא לפחות 1+ n/2שזה יותר מ , n/2ולכן הוא איבר רוב של .Bבמקרה השני והשלישי, מספר המופעים של xב Bהוא אחד פחות מאשר ב ,Aכלומר לפחות ,n/2ולכן גם במקרה זה הוא איבר רוב של .B ד.
)1(. )מספיק היה לתת הסבר מילולי פחות פורמאלי מזה שיוצג לעיל(. נוכיח באינדוקציה על jכי הטענה
מתקיימת לכל jבנקודה בה נבדקים תנאי ה ) whileולכן בפרט תתקיים כאשר אחד מהם לפחות מופר ויוצאים לכן מהלולאה(. הבסיס: 1=) jלפני האיטרציה הראשונה(. במצב זה , k-j+1=kכלומר תת המערך מכיל רק את ,A[k]=valואכן באיתחול 1= countכנדרש. צעד האינדוקציה: נניח מתקיים עבור 1- jנוכיח עבור . jלפי הנחת האינדוקציה, בתחילת האיטרציה הקודמת )כאשר הערך של jהיה קטן ב 1(, countהיה מספר ההופעות של הערך valבתת המערך ] A[k-j+2,...,kפחות מספר ההופעות של ערכים אחרים באותו תת מערך. במהלך האיטרציה, אם A[k-j+1]=valאז הערך של countגדל ב 1 )ואכן ההפרש גדל ב 1( ואחרת הוא קטן ב 1 )ואכן ההפרש קטן ב 1(. מכאן שצעד האינדוקציה תקף. )2(. כיוון שבתחילת כל איטרציה של לולאת ה ,whileנבדק ש 0> countו countקטן לכל היותר ב 1 בכל איטרציה, הרי שכאשר יוצאים מלולאת , whileאו ש 0> countאו ש 0= .countבמקרה הראשון, לפי תת-הסעיף הקודם, מספר הפעמים ש valמופיע ב ] A[1,...,kגדול ממספר הפעמים שמופיע כל איבר אחר, כלומר, valהוא איבר הרוב בתת המערך הזה. במקרה השני מספר הפעמים ש valמופיע ב ] A[1,...,kשווה למספר הפעמים שמופיע איבר אחר. מכאן שכל איבר מופיע לכל היותר מחצית הפעמים, ומכאן נובע שאין איבר רוב. )3(. נפעל לפי ההדרכה. בסיס האינדוקציה, 1= .kבמקרה זה יש בתת המערך איבר יחיד והוא איבר הרוב. השגרה אכן מחזירה איבר זה בשורה 3. צעד האינדוקציה: נניח כי טענת האינדוקציה מתקיימת לכל ) 0<t<k ,tכלומר, אם ] A[1,...,tמכיל איבר רוב אז ) Candidate(A,tתחזיר אותו( ונוכיח עבור .kלפי תנאי הסיום של לולאת ה ,while ומכיוון ש jגדל ב 1 בכל איטרציה, ו countגדל ב 1 או קטן ב 1 בכל איטרציה, הרי שהשגרה יוצאת
מלולאת ה whileאו כאשר j==kאו כאשר 0==) countאו ששניהם מתקיימים(. נתבונן בשני המקרים.
אם j==kאזי לפי סעיף ד)2(, אם יש ב ] A[1,...,kאיבר רוב אזי הוא יוחזר וצעד האינדוקציה מתקיים
)ללא צורך בשימוש בהנחת האינדוקציה(. אחרת, 0== .countלפי סעיף ד)1( זה אומר שמספר המופעים
של valזהה למספר המופעים של איברים השונים ממנו. אם נחשוב עליהם כמחולקים לזוגות, )(val,z
כאשר ,zvalהרי לפי סעיף ג, אם יש ב ] A[1,...,kאיבר רוב אזי הוא גם איבר הרוב של ].A[1,...,k-j כיוון ש 2 , jהרי k-j<kולפי הנחת האינדוקציה, הקריאה ל ) Candidate(A,k-jתחזיר את איבר הרוב
של ] A[1,...,k-jכנדרש. כיוון שהוכחנו שהטענה מתקיימת לכל kהרי בפרט היא מתקיימת עבור .k=n