שאלת מבחן באלגוריתמים - האוניברסיטה הפתוחה 2021 - תכנות דינמי

שאלה 2 – תכנון דינאמי (תת-סדרה עולה מרבית)

נתונה סדרה של מספרים שלמים שונים זה מזה. תת-סדרה של הינה סדרה מהצורה שבה , וסדר האיברים בתת-הסדרה זהה לסדר שלהם ב-. תת סדרה נקראת עולה אם .

הציגו אלגוריתם למציאת תת-סדרה עולה שאורכה מרבי. בניתוח זמן הריצה הניחו, שכל פעולה אלמנטרית על מספרים (כמו חיבור, חיסור או השוואה) מתבצעת בזמן . ניקוד: אלגוריתם שרץ בזמן ריבועי מקנה 19 נקודות. אלגוריתם משופר שרץ בזמן מקנה 33 נקודות.
העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
האוניברסיטה הפתוחהמועד 752021סמסטר א
תכנות דינמיניתוח אלגוריתמיםסיבוכיותחיפוש בינארי
בפתרון הריבועי, הגדירו לכל אינדקס את אורך תת-הסדרה העולה הארוכה ביותר המסתיימת באיבר . לפתרון היעיל יותר, חשבו כיצד לשמור מערך ממוין של האיברים הקטנים ביותר האפשריים עבור כל אורך של תת-סדרה, ולעדכן אותו באמצעות חיפוש בינארי.
בעיית מציאת תת-סדרה עולה מרבית היא בעיה קלאסית הנפתרת באמצעות תכנות דינמי. נציג שני פתרונות, הראשון בסיבוכיות והשני בסיבוכיות .
פתרון בסיבוכיות
הגדרת תת-בעיה:
נגדיר מערך dp בגודל
. עבור כל אינדקס (מ- עד ), dp[i] יכיל את אורכה של תת-הסדרה העולה הארוכה ביותר המסתיימת באיבר .

נוסחת הנסיגה (רקורסיה):
כדי לחשב את dp[i], עלינו למצוא איבר קודם
(כלומר, ) שקטן מ- (), ושנותן את תת-הסדרה העולה הארוכה ביותר שניתן להרחיב באמצעות . אם נמצא כזה, הרי שאורך תת-הסדרה החדשה המסתיימת ב- יהיה dp[j] + 1. אנו נרצה לבחור את ה- שממקסם ערך זה. אם לא קיים כזה, פירוש הדבר ש- הוא האיבר הקטן ביותר עד כה, ולכן הוא פותח תת-סדרה חדשה באורך 1.

לפיכך, נוסחת הנסיגה היא:כאשר המקסימום על קבוצה ריקה מוגדר כ-0.

אלגוריתם:
1. אתחל מערך dp בגודל
, כאשר כל תאיו מאותחלים ל-1 (כל איבר בפני עצמו הוא תת-סדרה עולה באורך 1).
2. עבור
מ- עד :
א. עבור
מ- עד :
i. אם
וגם :
- עדכן:
.
3. התשובה הסופית היא הערך המקסימלי במערך dp, כלומר
.

ניתוח סיבוכיות:
- זמן ריצה: האלגוריתם מכיל שתי לולאות מקוננות. הלולאה החיצונית רצה
פעמים, והפנימית רצה עד פעמים. בסך הכל, מספר הפעולות הוא פרופורציונלי ל- .
- מקום: אנו משתמשים במערך עזר dp בגודל
, ולכן סיבוכיות המקום היא .
פתרון משופר בסיבוכיות
ניתן לייעל את הפתרון הקודם. צוואר הבקבוק בפתרון הריבועי הוא החיפוש אחר בכל איטרציה. במקום זאת, נשנה את הגישה ונשמור מידע אחר.

תובנה מרכזית:
נחזיק מערך Tails שבו Tails[k] הוא האיבר הקטן ביותר שבו יכולה להסתיים תת-סדרה עולה באורך
. חשוב להבין שמערך זה אינו תת-סדרה עולה בעצמו, אלא כלי עזר. תכונה חשובה של Tails היא שהוא תמיד יהיה ממוין בסדר עולה.

אלגוריתם:
1. אתחל מערך Tails ריק.

2. עבור כל איבר
בסדרה (מ- עד ):
א. אם Tails ריק או ש-
גדול מהאיבר האחרון ב-Tails:
- הוסף את
לסוף Tails. פעולה זו מאריכה את תת-הסדרה העולה הארוכה ביותר שמצאנו עד כה.
ב. אחרת (כלומר,
אינו גדול מהאיבר האחרון ב-Tails):
- מצא את האינדקס
של האיבר הראשון ב-Tails שגדול או שווה ל-. מכיוון ש-Tails ממוין, ניתן לעשות זאת באמצעות חיפוש בינארי.
- החלף את האיבר ב-Tails באינדקס
ב-. פעולה זו לא משנה את אורך Tails, אך היא "משפרת" את הפוטנציאל לעתיד על ידי הקטנת ערך הסיום של תת-סדרה באורך .

3. אורך תת-הסדרה העולה המרבי הוא האורך הסופי של המערך Tails.

דוגמת הרצה: - : Tails = [3]
-
: , הוסף. Tails = [3, 4]
-
: החלף את 3. Tails = [-1, 4]
-
: , הוסף. Tails = [-1, 4, 5]
-
: , הוסף. Tails = [-1, 4, 5, 8]
-
: החלף את 4. Tails = [-1, 2, 5, 8]
-
: החלף את 5. Tails = [-1, 2, 3, 8]
-
: , הוסף. Tails = [-1, 2, 3, 8, 12]
-
: החלף את 8. Tails = [-1, 2, 3, 7, 12]
-
: החלף את 12. Tails = [-1, 2, 3, 7, 9]
-
: , הוסף. Tails = [-1, 2, 3, 7, 9, 10]

האורך הסופי של Tails הוא 6, וזהו אורך תת-הסדרה העולה המרבית. (למשל: -1, 2, 3, 7, 9, 10).

ניתוח סיבוכיות:
- זמן ריצה: אנו עוברים על כל
האיברים של סדרת הקלט. עבור כל איבר, אנו מבצעים פעולת חיפוש בינארי על המערך Tails, שאורכו לכל היותר . חיפוש בינארי לוקח כאשר הוא אורך Tails הנוכחי. לכן, הסיבוכיות הכוללת היא .
- מקום: אנו משתמשים במערך עזר Tails שאורכו לכל היותר
, ולכן סיבוכיות המקום היא .