ABA


"חידה - אתגר: (נוסף רמז)"
גירסת הדפסה        
קבוצות דיון פיתוח, תיכנות ובניית אתרים נושא #15865 מנהל    סגן המנהל    מפקח   Winner    צל"ש   מומחה  
אשכול מספר 15865
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   09:16   03.05.10   
אל הפורום  
  חידה - אתגר: (נוסף רמז)  
 
עוגן האשכול הוסר בתאריך 09.05.10 בשעה  23:54  על-ידי Net_Boy, (מנהל הפורום)
 
נתון מבנה נתונים הבנוי מ"רשימות מצטלבות".
בידכם המצביעים לראשי הרשימות: התאים a1 ו- b1.
הרשימות הן חד כיווניות!
הקליטה למבנה הנתונים המוזר הזה, מתבצעת ע"י הוספת איבר בראש הרשימה.
כלומר לפני a1 או לפני b1.
אחת לכמה זמן, מתקבלת פקודה להוריד את אחד מהענפים בפיצול,
כך שמיד אחריו נישאר עם רשימה מקושרת ליניארית, רגילה.

מכיוון שכך, לאחר מספר סיבובי קליטה\הסרת "ענף",
נקבל ש-n גדול בכמה סדרי גודל מ-m או k.

המטרה: להראות איך ניתן לבצע את פעולת "הסרת ענף" ב-

O(max{m,k})

שימו שאתם צריכים להגיע בדיוק לאיבר x1.
כמו כן, לא נתון לכם איזה ענף יותר גדול, וייתכן מצב של "ענף ריק".
(כלומר אם A ענף ריק, אז: a1=x1)
עריכה:הגבלה נוספת ששכחתי לציין קודם: זיכרון מותר לשימוש: O(1)

בהצלחה!

רמז:
יש לחידה זו שני פתרונות (שידועים לי),
אחד הפתרונות מאד פשוט ונעזר ב-2 פוינטרים בלבד.

נסו לחשוב איך הייתם פותרים את התרגיל בעזרת 2 פוינטרים,
אם הייתי מאפשר לזמן הריצה להיות

O((max{k,m})^2)

עכשיו, תנסו לשכלל ולשפר את הרעיון לזמן המקורי.


                                שתף        
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

  האשכול     מחבר     תאריך כתיבה     מספר  
  זה יחסית פשוט, שיהיה בהצלחה. Deuce  03.05.10 21:12 1
  ממ אם הבנתי נכון את המשימה ronen333  04.05.10 15:09 2
     אני יחכה שעוד כמה ינסו, ואם אף אחד לא יצליח אתן רמז. Zippo  04.05.10 15:31 3
  מכתב ronen333  04.05.10 17:47 4
     קצת קשה לעקוב אחרי הקוד, אבל זה לא הכיוון. Zippo  05.05.10 00:04 5
         TO DEL זה האיבר למחוק.. ronen333  05.05.10 14:18 7
  רעיון קצת שונה ronen333  05.05.10 14:16 6
     נעבור על כל אחת מהרשימות? Zippo  05.05.10 17:25 8
         לא נראה לי שהבנת את הרעיון. ronen333  05.05.10 17:40 9
             מילת המפתח היא ''כל''. אתה לא יכול לעבור על כל הרשימה Zippo  05.05.10 19:01 16
                 מכתב ronen333  05.05.10 19:04 18
                     אני יודע שזה מה שהתכוונת אליו. Zippo  05.05.10 21:23 26
                         אני רואה שעדיין לא הבנת ronen333  05.05.10 21:28 27
                             הבנתי :) Zippo  05.05.10 21:35 28
  טוב אז למצוא את X1 פאביו ג'וניור 05.05.10 17:53 10
     אתה משנה מבנה נתונים יא רמאי קטן :P ronen333  05.05.10 18:00 11
         חחח כע טריק מגעיל ^^ פאביו ג'וניור 05.05.10 18:03 12
             גם אני חשבתי ללכת לכיוון הזה. ronen333  05.05.10 18:06 13
                 לא להפוך את הכל... להפוך בזמן הריצה פאביו ג'וניור 05.05.10 18:07 14
     פתרון יפה! אבל: Zippo  05.05.10 18:57 15
         אתה רציני? יכלנו לשנות את המבנה נתונים? ronen333  05.05.10 19:02 17
             בדיוק עניתי לו שלא. Zippo  05.05.10 19:15 19
                 ככה התייחסתי מההתחלה ronen333  05.05.10 19:23 20
                     תאכלס עכשיו הזיכרון בO(1) הרס לי את כל הכיוון מחשבה חחח פאביו ג'וניור 05.05.10 20:25 21
                         כן ביאס לי את התחת XD ronen333  05.05.10 20:50 22
                             רק שזה זמן ממוצע... לא במקרה הגרוע ביותר... פאביו ג'וניור 05.05.10 20:58 23
                                 אכן X= ronen333  05.05.10 21:11 24
                                     אל תלכו רחוק מדי. הפתרון פשוט וטריקי. Zippo  05.05.10 21:18 25
  רעיון כללי MiP 06.05.10 03:11 29
     אם הבנתי אותך, זה רץ ב-O(n^2) שזה ממש לא טוב. Zippo  06.05.10 06:50 30
     אני גם לא הבנתי אותך.. ronen333  06.05.10 11:16 31
  ניסיון ראשוני לפתור (הצלחתי ב-dlogd כאשר d = max m k). Deuce  07.05.10 05:52 32
     אייל שפכת אותי :P ronen333  07.05.10 11:31 33
         לא מסכים איתך בנוגע לרשימה. Deuce  07.05.10 15:48 34
             אייל, רק לציין, כשאני אומר O(d) Zippo  07.05.10 16:28 35
             רשימה מקושרת סטנדרטית מבחינתי זה הדבר הבא: ronen333  07.05.10 18:03 39
  פתרון סופי. Deuce  07.05.10 17:47 36
     יפה מאוד אייל! ronen333  07.05.10 17:58 38
     זה אכן הפתרון - תיקון קל. Zippo  07.05.10 19:04 40
         לא ממש טעיתי, הפתרונות שלנו קצת שונים ;) Deuce  07.05.10 20:49 41
             מכיוון שמדובר ברשימה מקושרת רגילה, Zippo  08.05.10 20:54 43
     יפה ldan192  08.05.10 13:43 42
  אני חושב שיש לי פתרון שמשתמש בעובדה ש-X * Y * X = Y ldan192  07.05.10 17:48 37

       
Deuce 
חבר מתאריך 1.9.08
6225 הודעות
   21:12   03.05.10   
אל הפורום  
  1. זה יחסית פשוט, שיהיה בהצלחה.  
בתגובה להודעה מספר 0
 
חשבתי על הכללה מעניינת, אני אתן אותה לאחר שיהיה כאן פותר.






                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   15:09   04.05.10   
אל הפורום  
  2. ממ אם הבנתי נכון את המשימה  
בתגובה להודעה מספר 0
 
   ערכתי לאחרונה בתאריך 04.05.10 בשעה 15:16 בברכה, ronen333
 
אז לא הצלחתי לחשוב על פתרון שפותר את זה בסיבוכיות הזאת בלי לדעת איזה מרשימות הפיצול הוא הארוכה יותר.

אפשר רמז? :P


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   15:31   04.05.10   
אל הפורום  
  3. אני יחכה שעוד כמה ינסו, ואם אף אחד לא יצליח אתן רמז.  
בתגובה להודעה מספר 2
 
אבל אני מאמין שאתה לא צריך רמז.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   17:47   04.05.10   
אל הפורום  
  4. מכתב  
בתגובה להודעה מספר 0
 
   ערכתי לאחרונה בתאריך 04.05.10 בשעה 17:55 בברכה, ronen333
 
יצא לי פתרון די מסורבל ומטומטם אבל פתרון..
אמ, לא אמרת מה הממשק אז אני אניח שיש פעולת remove שמסירה צומת מרשימה רגילה.

הפרוצדורה:


void delete_node(node *to_del,node *a1,node *b1)
{
node *p1=a1;
node *tp1=p1;
node *p2=b1;
node *tp2=p2;
int c1,c2,tc1,tc2;
c1=c2=tc1=tc2=0;
while(to_del != p1 && to_del != p2 && to_del != tp1 && to_del != tp2 && p1!=p2 && tp1!=tp2)
{
while(c1<c2)
{
++c1;
p1=p1->next;
}
++c2;
p2=p2->next;
while(tc2<tc1)
{
++tc2;
tp2=tp2->next;
}
++tc1;
tp1=tp1->next;
}

if(p1 != p2 || tp1 != tp2 && to_del==p1 || to_del==tp1)
remove(to_del,a1);
if(p1 != p2 || tp1 != tp2 && to_del==p2 || to_del==tp2)
remove(to_del,a2)
}

וזהו, זה עושה את העבודה בסיבוכיות הנדרשת.
בהנחה שבאמת הבנתי את התרגיל.. XD.
כל הקושי פה היה לפי הבנתי זה לוודא שלא נמחק המהרשימה הלינארית הרגילה באורך n, אלא רק מהרשימה המצטלבת באורך K או M.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   00:04   05.05.10   
אל הפורום  
  5. קצת קשה לעקוב אחרי הקוד, אבל זה לא הכיוון.  
בתגובה להודעה מספר 4
 
נסה לא לכתוב בשפת תכנות פורמלית, אלא אלגוריתם בעברית.


1.0 בצע א'
2.0 כל עוד לא ב'
---2.1 בצע ג'
3.0 אם ד':
---3.1 בצע בלולאה:
------3.1.2 פעולה מסויימת
4.0 אחרת:
---4.1 בצע...

וכו'...

בנוגע למה שכתבת. מה מייצג node *to_del?
הרשימות מתחברות באיבר לא ידוע שאתה צריך למצוא.
אני רוצה שתסיר את האיברים (למשל) a1-ak כך שאני ישאר עם רשימה מקושרת ליניארית b1,..,bm,x1,..,xn
פעולת ההסרה עצמה לא חשובה.

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

O(k)/O(m)
שלא תוסיף (בסדר גודל) לזמן הריצה המבוקש.

תתייחס לשאלה כאילו ביקשו ממך למצוא את x1, זה ה"בשר" בחידה.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   14:18   05.05.10   
אל הפורום  
  7. TO DEL זה האיבר למחוק..  
בתגובה להודעה מספר 5
 
   הרעיון בכללי היה להניח שאחד מהרשימות הוא קצר יותר, ואז למצוא את האיבר X1, ובמקביל לעשות את ההפוך לו (עם מצביעים מקבילים).

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


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   14:16   05.05.10   
אל הפורום  
  6. רעיון קצת שונה  
בתגובה להודעה מספר 0
 
   נעבור על כל אחת מהרשימות, ונוסיף לטבלת גיבוב את הכתובת של כל איבר(הכתובת זה המפתח).
לפני כל הוספה נבדוק אם הוא קיים ברשימה (טטא של 1 בהנחה שמקדם העומס הוא קבוע). אם הוא קיים אזי זה האיבר X1, אם לא נמשיך..
זה יפתור את זה בסיבוכיות הנדרשת..אבל אם אני לא טועה רק בזמן ריצה הממוצע.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   17:25   05.05.10   
אל הפורום  
  8. נעבור על כל אחת מהרשימות?  
בתגובה להודעה מספר 6
 
זאת בדיוק הבעיה. אתה לא יכול. אתה תגיע אחרי ריצה אחת ל-xn שגדול בכמה סדרי גודל מ-k או m.
אין לך שום אינדיקטור עבור x1 מלבד העובדה שיש איפשהוא פוינטר ברשימה אחרת המצביע אליו גם.

אגב, הפתרון הוא "טריקי".
כך שאם נראה לך שעלית על משהו טריוויאלי, כנראה שזה לא הכיוון הנכון.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   17:40   05.05.10   
אל הפורום  
  9. לא נראה לי שהבנת את הרעיון.  
בתגובה להודעה מספר 8
 
   זה בחיים לא יגיע לN אם יש רשימת פיצול כפי שאמרת. כי זה תמיד יגיע לכתובת כפולה.
ואני יודע שאין לי שום אינדקטור לX1 לכן אני מחפש אחר כתובות כפולות. כי X1 הוא הראשון משבו אנו נתקלים.


ומה זה "אני לא יכול לעבור על כל אחת מהרשימות"? יש לי מצביע לכל תחילת ענף- אזי יש לי.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   19:01   05.05.10   
אל הפורום  
  16. מילת המפתח היא ''כל''. אתה לא יכול לעבור על כל הרשימה  
בתגובה להודעה מספר 9
 
מפני שהרשימה מתחילה במצביע שיש לך, ומסתיימת הרחק שם ב-xn.
כמו כן, שים לב לדיוק שעניתי למטה.
הגבלה נוספת ששכחתי לציין היא שמותר לך להשתמש בעלות זיכרון בסדר גודל של O(1)


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   19:04   05.05.10   
אל הפורום  
  18. מכתב  
בתגובה להודעה מספר 16
 
   שאמרתי כל, התכוונתי לכל הענף. לא לכל הרשימה. ככה שאני עובר רק על K או M פלוס אחד.

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


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   21:23   05.05.10   
אל הפורום  
  26. אני יודע שזה מה שהתכוונת אליו.  
בתגובה להודעה מספר 18
 
אבל אין לך דרך לדעת כמה זה בדיוק k או m ולכן, גם לא אפשרי לרוץ בדיוק כמספר האיברים.
שום דבר אינו ידוע לך מלבד a1 ו- b1


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   21:28   05.05.10   
אל הפורום  
  27. אני רואה שעדיין לא הבנת  
בתגובה להודעה מספר 26
 
   ערכתי לאחרונה בתאריך 05.05.10 בשעה 21:31 בברכה, ronen333
 
למרות שזה כבר לא רלוונטי לחידה שלך (בגלל הסיבוכיות מקום) אני אסביר:
אתה עובר בכל ענף פיצול, קרי: a1 וb1, ומתקדם ב1 בכל פעם תוך הוספה לטבלת גיבוב.
לפני כל הוספה אתה שואל "האם הכתובת הנ"ל שאני עומד להוסיף קיימת בטבלת גיבוב?" אם התשובה חיובית אזי הגעת לX1, אם לא אז אתה מוסיף לטבלה וממשיך בסריקה שלך.
הסיבה שזה K או M בסיבוכיות זמן ריצה היא שלא משנה מה אתה תתקל בהתחלת הרשימה הלינארית(במילים אחרות- סוף הרשימה K או M) ושם תיפסק הסריקה, כי קיימת הכתובת הזאת בטבלת גיבוב.
ולבדוק אם קיים כתובת בטבלה גוזל זמן קבוע.

זה עובד בדוק- מימשתי את זה גם.
מקווה שעכשיו הבנת...


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   21:35   05.05.10   
אל הפורום  
  28. הבנתי :)  
בתגובה להודעה מספר 27
 


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
פאביו ג'וניור

   17:53   05.05.10   
אל הפורום  
  10. טוב אז למצוא את X1  
בתגובה להודעה מספר 0
 
   ב O של המקסימום...
מה שנעשה זה נוסיף לכל איבר ברשימה עוד BOOL (תעטוף כל איבר... תקרא לזה איך שאתה רוצה חח)
נעבור במקביל תא מפה תא מפה ונסמן בכל אחד מהם את הBOOL בTRUE..
ברגע שאתה מגיע מאחד הרשימות לBOOL שהוא TRUE מצאת את X1...
זה יעשה בO(max{m,k} + 1) ששווה ל O(max{m,k})


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   18:00   05.05.10   
אל הפורום  
  11. אתה משנה מבנה נתונים יא רמאי קטן :P  
בתגובה להודעה מספר 10
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
פאביו ג'וניור

   18:03   05.05.10   
אל הפורום  
  12. חחח כע טריק מגעיל ^^  
בתגובה להודעה מספר 11
 
   פסדר אני חושב עכשיו לכיוון של הצבעה הפוכה או לבנות במקביל רשימה שמצביע הפוך :\


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   18:06   05.05.10   
אל הפורום  
  13. גם אני חשבתי ללכת לכיוון הזה.  
בתגובה להודעה מספר 12
 
   אבל-
א. אתה תצטרך לשנות את המבנה כי בסופו של דבר יש לך 2 מבציעים.
ב.להפוך את הכל זה לעבור N, מה שהורס את הסיבוכיות.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
פאביו ג'וניור

   18:07   05.05.10   
אל הפורום  
  14. לא להפוך את הכל... להפוך בזמן הריצה  
בתגובה להודעה מספר 13
 
   וגם להעתיק את המבנה בזמן הריצה...
לא חשבתי על זה עד הסוף אני עכשיו מנסה לראות מה יצא מזה...


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   18:57   05.05.10   
אל הפורום  
  15. פתרון יפה! אבל:  
בתגובה להודעה מספר 10
 
בוא נניח לצורך העניין שאתה לא יכול לשנות את מבנה הנתונים, או לסמן לעצמך בצד. זיכרון פנוי לשימושך:
O(1)

סימון משתנה בוליאני בכל איבר זאת תוספת זיכרון בסדר גודל של:

O(n)


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   19:02   05.05.10   
אל הפורום  
  17. אתה רציני? יכלנו לשנות את המבנה נתונים?  
בתגובה להודעה מספר 15
 
   אז מה חידה בזה? "-.-
אני יכול להגיד לך גם "אני שומר מצביע במבנה נתונים לאיבר הראשון X1".


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   19:15   05.05.10   
אל הפורום  
  19. בדיוק עניתי לו שלא.  
בתגובה להודעה מספר 17
 
תתייחס למבנה הנתונים כאל קלט.
אתה צריך לכתוב אלגוריתם, שבהינתן שני מצביעים לרשימה מקושרת מתמזגת, עליו למצוא בזמן המבוקש את נקודת החיבור.

כל השאר, זה "קישוט" לשאלה.
לא מעניין אותי מה תכ'לס מטרת האלגוריתם, אם כמו שאמרתי להסיר את אחת הרשימות, או משהו אחר...


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   19:23   05.05.10   
אל הפורום  
  20. ככה התייחסתי מההתחלה  
בתגובה להודעה מספר 19
 
   פשוט הייתי בהלם מזה שאמרת לו יפה על זה שהוא שינה לך את המבנה נתונים חחח...

זרוק עצם.. אין לי כיוון בלי להקצות מקום.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
פאביו ג'וניור

   20:25   05.05.10   
אל הפורום  
  21. תאכלס עכשיו הזיכרון בO(1) הרס לי את כל הכיוון מחשבה חחח  
בתגובה להודעה מספר 20
 
   פסדר נו זה היה סתם פתרון כיסתו"ח מה שנתתי חחחח


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   20:50   05.05.10   
אל הפורום  
  22. כן ביאס לי את התחת XD  
בתגובה להודעה מספר 21
 
   הטבלת גיבוב פותרת את זה יופי.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
פאביו ג'וניור

   20:58   05.05.10   
אל הפורום  
  23. רק שזה זמן ממוצע... לא במקרה הגרוע ביותר...  
בתגובה להודעה מספר 22
 
   זה הקטע של HASH TABLES :\


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   21:11   05.05.10   
אל הפורום  
  24. אכן X=  
בתגובה להודעה מספר 23
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   21:18   05.05.10   
אל הפורום  
  25. אל תלכו רחוק מדי. הפתרון פשוט וטריקי.  
בתגובה להודעה מספר 24
 
קצת תחכום. לא היית מפרסם חידה עם פתרון "משעמם"...


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
MiP
חבר מתאריך 24.5.05
782 הודעות
   03:11   06.05.10   
אל הפורום  
  29. רעיון כללי  
בתגובה להודעה מספר 0
 
   בגדול בכל פעם לשמור מצביע של כל תא לתא הבא(->) בענף מסויים ואז לעבור על
הענף השני ולראות מתי המצביעים מצתלבים לאותו התא(כתובת זהה).
ונמצא נאתר את X1 ע"פ המקס' M או K ומשם כבר הסרה כפי שאתה טוען לא משנה כיצד.



                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   06:50   06.05.10   
אל הפורום  
  30. אם הבנתי אותך, זה רץ ב-O(n^2) שזה ממש לא טוב.  
בתגובה להודעה מספר 29
 
"...ואז לעבור על הענף השני..." - איך תדע מתי הוא נגמר?
אורך הענף לא ידוע לך. אתה תגיע עד xn. כמו כן, על כל חוליה בשרשרת,
אתה רוצה לרוץ לכל אורך הענף. שזה זמן ריבועי, גם אם היית יודע את אורך הענף.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   11:16   06.05.10   
אל הפורום  
  31. אני גם לא הבנתי אותך..  
בתגובה להודעה מספר 29
 
   אני מניח שמה שהצעת זה לא N^2 כמו שזיפו טוען, אבל אתה בעצם אומר "אני עובר עם מצביעים עד שאני נתקל בהתלכדות" וזה בעצם כל הקושי.. איך אתה מוצא את ההתלכדות? הם לא באותו אורך, ואתה לא יודע כמה עליך לעבור בכל אחד.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Deuce 
חבר מתאריך 1.9.08
6225 הודעות
   05:52   07.05.10   
אל הפורום  
  32. ניסיון ראשוני לפתור (הצלחתי ב-dlogd כאשר d = max m k).  
בתגובה להודעה מספר 0
 
ערכתי לאחרונה בתאריך 07.05.10 בשעה 06:15 בברכה, Deuce
 
קודם כל אני אתוודה, כשרשמתי את התגובה בהתחלה חשבתי שאפשר להניח החזרת גודל הרשימה ב-O(1) שזאת הנחה סבירה בסה"כ. גודל הרשימה הכוונה מספר החוליות ברשימה שמתחילה ב-a1 וב-b1 (לא M ו-K לצורך העניין). עם קריאת התגובות שנרשמו פה, נראה היה שאי אפשר להניח זאת. שאלתי את Zippo והוא אמר לי שלא

עכשיו אני כמוכם מנסה לפתור בעצמי.
אם נגיד ל-2 המצביעים פשוט לרוץ על כל האפשרויות:
א. מצביע 1 מתקדם 0 מקומות, מצביע 2 מתקדם מקום 1 ולהפך.
ב. מצביע 1 מתקדם 1 מקומות, מצביע 2 מתקדם מקום 0 ולהפל.
ג. מצביע 1 מתקדם 1 מקומות, מצביע 2 מתקדם 1 מקום.
ד. מצביע 1 מתקדם 2 מקומות, מצביע 2 מתקדם 0 מקום ולהפך.
וכו' ...
אפשר לרשום בזוגות סדורים:

(i,j) - Pointer 1 moves i'th steps, then Pointer 2 moves j'th steps and vice versa

לדאוג שההרצה תהיה מבוקרת ברמה של לא נרוץ למשל על הזוג (5,2) לפני שכיסינו את כל הזוגות בהם מופיעות רק הספרות 0-4.

אנחנו נגלה את התא כאשר נרוץ פשוט על הזוג (m,k). סיבוכיות זמן הריצה הי איפוא m^2*k^2 שזה לא להיט (הריבועים שם כי כל פעם אנחנו חוזרים עם המצביעים להתחלה).
(אני ברגע זה חושב בעצמי, לכן ההסברים מתגבשים בזה הרגע )
נסמן d = max(m,k).
נניח אני מסתכל על איזשהו זוג (i,i) כש-i גדול מ-d. אני יודע שבודאות שניהם חצו את המכשול. אבל יש מישהו מהיר יותר, לכן בהכרח או ש-P1 יעקוף את P2 ואז בריצה השנייה (ש-P2 מתחיל) תהיה התנגשות. או להפך. אבל העיקר שהזוג הזה תופס.
כלומר יכולנו פשוט לרוץ על (i,i) כש-i הולך ועולה. בתפיסה הראשונה נדע גם מי מגיע מהר יותר לאיחוד (זה שתופס מן הסתם). נשים לב שהתפיסה הראשונה גם מבטאת בידיוק את max(m,k) שזה קצת מפתיע. למעשה היינו יכולים פשוט להגיד להם תרוצו כל פעם i צעדים כשפעם הראשון מתחיל, אחריו השני ואז להפך והתפיסה הראשונה בעצם תבטא את המקסימום, כי התפיסה הראשונה אומרת שהמצביע שמצביע על הרשימה הארוכה יותר סוף סוף נכנס לאיחוד ואז נתפס.
אז כמה זה עולה לנו עד פה? d^2
הבעייה שאנחנו לא יודעים מי המהיר יותר אז אנחנו כל פעם מחליפים את הריצה וזה מוסיף לנו ריבוע. אם למשל היינו רצים גם בקפיצות לוגירתמיות של 1,2,4,8 ועושים חיפוש בינארי על ה-d המיימלי אז זה היה עולה כבר dlog d, אבל זה עדיין לא ליניארי.
נו כל זה ב-6 בבוקר, אולי מספיק להיום?

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






                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   11:31   07.05.10   
אל הפורום  
  33. אייל שפכת אותי :P  
בתגובה להודעה מספר 32
 
   ערכתי לאחרונה בתאריך 07.05.10 בשעה 12:08 בברכה, ronen333
 
אמרת עייף פעמיים.. אתה באמת מאוד עייף. טוס לישון :P.
נראה לי שפחות או יותר הבנתי את הרעיון, בגדול אחלה רעיון.
אבל קצת מסורבל לעשות משהו כזה...
ולא הבנתי איך אתה רוצה לעשות את החיפוש הבינארי שלך.. אסור להקצות מקום שהוא לא קבוע,הרשימה לא ממוינת,ואין לך איך לחזור אחורה.

נ.ב-להחזיר את גודל הרשימה בO של 1 זה לא הנחה סבירה בכלל. זה היה סביר והגיוני אם זה היה מערך.. אבל זה לא. רשימה זה אוסף דינאמי שאתה לא יודע את אורכו. אלא אם כן אתה מוסיף לו שיפורים, וזה לא המקרה פה.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Deuce 
חבר מתאריך 1.9.08
6225 הודעות
   15:48   07.05.10   
אל הפורום  
  34. לא מסכים איתך בנוגע לרשימה.  
בתגובה להודעה מספר 33
 
זאת הנחה סבירה שתהיה מתודה length() לרשימה. הדבר היחיד שזה דורש ממך זה הקצאה של מקום אחד בזכרון והגדלה/הקטנה בכל פעם שמסירים. במקרה הזה בגלל שיש קיצוץ ענף אז אולי זה לא סביר להניח.

אכן הייתי עייף, אני אסביר את הרעיון שוב:
נסמן את המצביע לרשימה הראשונה ב-P1 ואת המצביע לרשימה השנייה ב-P2.
הזוג (i,i) יתאר ריצה באופן הבא - מצביע P1 רץ i צעדים ועוצר, ואז מצביע P2 רץ i צעדים; אם הוא לא תפס אותו, אז מצביע P2 רץ i צעדים ועוצר ואז מצביע P1 רץ i צעדים ועוצר. בכל מקרה, אם i גדול מ-d אז מישהו יתפוס מישהו.
כשאני אומר חיפוש בינארי אני לא צריך להקצות מקום, אני מגדיל את i כל פעם בקפיצות של שתיים. בסופו של דבר אני אתפוס את ה-i הראשון שתהיה תפיסה כאשר:


d/2 <= i <= 2d
(תחשוב למה זה נכון, זה דיי פשוט).
ואז אני עושה חיפוש בינארי, כלומר יש לי קטע שאני יודע שב-i עדיין אין עצירה וב-2i יש אז אני בודק את 1.5i וכל פעם מקטין את הבעייה פי שניים. אני רק צריך לזכור את 2 קצוות הסגמנים. בגלל שהקטע הוא באורך O(d) אז החיפוש יעלה לי log d (בנוסף ל-log d הראשוניים שקפצתי).
סה"כ עשיתי log d קריאות להליכות כאלה - dlog d.






                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   16:28   07.05.10   
אל הפורום  
  35. אייל, רק לציין, כשאני אומר O(d)  
בתגובה להודעה מספר 34
 
הכוונה שיש קבוע כלשהוא c כך שזמן הריצה לא יעלה על c*d
ודי לחכימא ברמיזא...


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   18:03   07.05.10   
אל הפורום  
  39. רשימה מקושרת סטנדרטית מבחינתי זה הדבר הבא:  
בתגובה להודעה מספר 34
 
  

struct node
{
type info;
struct node * next;
}

לא יותר ולא פחות.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Deuce 
חבר מתאריך 1.9.08
6225 הודעות
   17:47   07.05.10   
אל הפורום  
  36. פתרון סופי.  
בתגובה להודעה מספר 0
 
ת'אמת שמה שרשמתי ממש כמעט פותר את זה, פשוט לא ניתחתי את הסיבוכיות כראוי.
קודם כל נסמן:
d = max(m,k)
P1 - Pointer to the the first list
P2 - Pointer to the second list

הרעיון:
הזוג (i,i) יסמן לנו ריצה באופן הבא:
P1 רץ i צעדים ועוצר. P2 רץ i צעדים ועוצר.
& vice versa:
P2 רץ i צעדים ועוצר. P1 רץ i צעדים ועוצר.
כל פעם רצים מהתחלת הרשימה.

נשים לתובנה כי אם i<d אז אף אחד לא יפגוש באף אחד (כי יש מצביע שעדיין לא הגיע להצטלבות). אם i>=d אז נשים לב שהמצביע שמגיע מהר יותר להצטלבות יחתוך את המצביע האיטי בדרך. לכן אם P1 למשל המצביע האיטי ו-P2 המהיר, אז כאשר P1 ירוץ ויעצר, P2 יתפוס אותו.

ניסיון ראשון:
להתחיל מ-i=0, להגדיל אותו כל פעם וברגע שיהיה מפגש אז i = d וסיימנו. זה עולה לנו d^2.
ניסיון שני:
נרוץ בקפיצות של i = 1,2,4,8, ...
נשים כי כאשר:

d <= i <= 2d

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

O(1 + 2 + 4 + ... + d/2 + d + 2d) = O(4d)

ולבסוף עוד ריצה אחרונה

בסה"כ O(d) כנדרש.






                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   17:58   07.05.10   
אל הפורום  
  38. יפה מאוד אייל!  
בתגובה להודעה מספר 36
 
   זה היה הכיוון שלי בנסיון הראשון שלי.. רק שלא טיפלתי בכל מקרה הקצה וזה לא עבד טוב.

כל הכבוד


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   19:04   07.05.10   
אל הפורום  
  40. זה אכן הפתרון - תיקון קל.  
בתגובה להודעה מספר 36
 
ציטוט: "P2 רץ i צעדים ועוצר. P1 רץ i צעדים ועוצר.
כל פעם רצים מהתחלת הרשימה."

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

פתרון זה הוא אכן dlogd, ואפילו בדקתי אותו על הנייר.

הפתרון הסופי:

לעולם לא נחזור אחורה! לא נבדוק מתחילת הרשימה, אלא רק מאיפה שהגענו...!"

נשתמש ב-2 פוינטרים, ו-2 קאונטרים.


1.0-while aPtr != bPtr
---1.1-loopCounter++
---1.2-if loopCounter is even:
------1.2.1-do 2^loopCounter times:
-----------1.2.1.1-aPtr <- aPtr(next)
-----------1.2.1.2-aCount++
---1.3-else if loopCounter is odd:
------1.3.1-do 2^loopCounter times:
-----------1.3.1.1-bPtr <- bPtr(next)
-----------1.3.1.2-bCount++
#exiting while loop when aPtr = bPtr
2.0-aPtr = a1, bPtr = b1
3.0-if aCount > bCount:
---3.1-do aCount - bCount times:
------3.1.1-aPtr <- aPtr(next)
4.0-else if bCount >= aCount:
---4.1-do bCount - aCount times:
------4.1.1-bPtr <- bPtr(next)
#now both pointers are at the same distance from x1:
5.0-while aPtr != bPtr
---5.1-aPtr <- aPtr(next)
---5.2-bPtr <- bPtr(next)
#we found x1!

בעצם עברנו את x1 לכל היותר ב-d איברים. (אם רשימה אחת ריקה ומתחילה מ-x1)
ובכל מקרה לא נבצע יותר מ-4d קידומי פוינטרים.

זהו אכן הפתרון הסופי.
כל הכבוד אייל!


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Deuce 
חבר מתאריך 1.9.08
6225 הודעות
   20:49   07.05.10   
אל הפורום  
  41. לא ממש טעיתי, הפתרונות שלנו קצת שונים ;)  
בתגובה להודעה מספר 40
 
שים לב לאופי השונה של הפתרונות שלנו:
אני אמרתי במקום להתקדם כל פעם i צעדים ולחזור להתחלה, לקפוץ בקפיצות של 2, כלומר לבדוק בהתחלה i = 0 ואז i = 1 ואז i = 2 ואז i = 4 ואז i = 8 וכו' ...

יוצא שבגלל שכל פעם אני קופץ בשתיים בבדיקה שלי אז אני מקבל d * טור גיאומטרי עם חצי שהולך ל-2.

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

הפתרון שכיוונת אליו לא פחות טוב, אבל קצת יותר קשה להוכיח את הנכונות שלו לדעתי.

בכל מקרה חידה לא קלה






                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   20:54   08.05.10   
אל הפורום  
  43. מכיוון שמדובר ברשימה מקושרת רגילה,  
בתגובה להודעה מספר 41
 
ולא סקיפ ליסט, למשל...
אתה לא יכול "לקפוץ" i צעדים בזמן של 1,
אלא תצטרך להתקדם בכל פעם מכל תא, לעוקב אחריו ברשימה.
מה שיעלה לך i פעולות.
כלומר, פוינטר אחד ירוץ 1+2+4+8+16+32... צעדים, והשני מתחיל מההתחלה בכל פעם.
כלומר: 1+(1+2)+(1+2+4)+(1+2+4+8)+(1+2+4+8+16)+(1+2+4+8+16+32)...

בכל אופן, ה"קאטץ'" היה לקדם את הפוינטרים בקפיצות הולכות וגדלות,
ולא להיות מקובע על x1, אלא לעבור אותו, ולהבין שזה לא משנה בזמני ריצה.

עבודה טובה!


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   13:43   08.05.10   
אל הפורום  
  42. יפה  
בתגובה להודעה מספר 36
 


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   17:48   07.05.10   
אל הפורום  
  37. אני חושב שיש לי פתרון שמשתמש בעובדה ש-X * Y * X = Y  
בתגובה להודעה מספר 0
 
(כאשר * = XOR)
אבל יותר מאוחר אבדוק אם הוא הגיוני.


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

תגובה מהירה  למכתב מספר: 
 
___________________________________________________________________

___________________________________________________________________
למנהלים:  נעל | תייק בארכיון | מחק | העבר לפורום אחר | מחק תגובות | עגן אשכול
       



© כל הזכויות שמורות ל-רוטר.נט בע"מ rotter.net