אז מה זה ליטקוד / LeetCode?
ליטקוד, זה שם של אתר אינטרנט, שמציג שאלות מראיונות עבודה למשרות של פיתוח תוכנה ותכנות. בעיות שונות בכתיבת קוד וכיו"ב. לפי רמות קושי / נושאים וכולי.
בעולם המתכנתים מקובל לומר ש "מי שמלטקד לא מפחד". דהיינו, מי שרגיל לפתור שאלות ליטקוד, לא מפחד מראיונות עבודה.
בפועל אנשים שרוצים לעבוד בהייטק במשרות של פיתוח, בדרך כלל הם יתרגלו שאלות ליטקוד, כדי להתכונן לראיונות עבודה.
למה לפתור שאלות ליטקוד?
1 - כי זה יגרום לך להיות יותר חכם וזה יעזור לך בכל תחומי החיים. 2 - כי זה כיף לאמץ את המוח וזאת הנאה שכלית שמי שיש לו שכל אז יודע שזה כיף לאתגר את המוח, כי יש לזה "טעם של שכל" (פילוסופיה / אהבת החוכמה).
3 - אם אתה מחפש עבודה בהייטק, אז זה יעזור לך להתקבל לעבודה הנחשקת. וכמובן שזה יעזור לך גם לשרוד את העבודה ולא רק להתקבל אליה. אבל זה כבר כפועל יוצא של זה שיש לך יותר שכל.
בנוסף חשוב מאוד לציין, כי שאלות ליטקוד, הן הזדמנות לפתח את החשיבה באופן מדוייק. ויש להן יתרון על פני מאמץ שכלי בתחומים אחרים. כי בליטקוד, יש בעיות מוגדרות וספציפיות, עם מערכת שבודקת בדיוק את הפתרון שלך, האם באמת הוא עובד וכמה הוא יעיל וכולי. ואז זה מגדיל את הסיכוי, שאתה לא בטעות תחשוב שאתה חכם, אלא באמת תהיה חכם. וזה תודות למנגנון הבדיקה של 0 או 1, שבודק בדיוק האם פתרת נכון או שלא.
מה זה אומר לפתור בעיה בליטקוד?
אז כשבאים לפתור בעיה בליטקוד, יש כמה עקרונות שהמערכת בודקת. 1 - האם פתרנו את הבעיה שהוצגה. 2 - האם ומהי היעילות אלגוריתמית, דהיינו: מהי היעילות (סיבוכיות זמן הריצה) של הפתרון שפתרנו את הבעיה. דהיינו, כמה פעולות היינו צריכים לבצע, ביחס לכמות המידע שנתנו לנו לנתח (ע"ע מה זה זמן ריצה). וגם מהי היעילות של משאבי המחשב / משאבי הזיכרון (סיבוכיות מקום) שהשתמשנו בהם כדי לפתור את הבעיה.
מה זה אומר שפתרנו את השאלה?
אז לפתור את השאלה, אפשרי באופן חלקי או באופן מלא. וזה כמובן בלי קשר ליעילות של הפתרון. ולפתור שאלה באופן חלקי, זה אומר שהפתרון אכן יפתור מצבים מסויימים של השאלה. אבל פתרון מלא של השאלה, הוא רק כאשר הפתרון שהצענו לפתור את השאלה, יפתור אותה בכל המצבים האפשריים שהאתר LeetCode יבדוק את הפתרון שלנו.
כי בצוות של האתר ליטקוד, יש אנשים שלוקחים פתרונות של אנשים ומנסים להקריס את הפתרונות האלו בכל מיני מקרה קצה כאלו ואחרים. ולפתור את השאלה מבחינת ליטקוד, זה רק כאשר הפתרון שלנו עובר את כל מצבי הבדיקה TestCase שהם הגדירו לבדוק את הפתרון שלנו.
או במילים אחרות, זאת לא רק חוכמה לדעת לפתור שאלות בליטקוד, אלא זאת גם חוכמה להבין איך לפתור את השאלה בכל מצב אפשרי. וזאת גם חוכמה להבין על כל פתרון, האם ובאילו מצבים הוא לא יפתור את השאלה. דהיינו, להבדיל בין פתרון אפשרי, שרק אפשרי שהוא יעבוד בחלק מהמקרים, לבין פתרון מחוייב, שמחוייב שהוא יעבוד בכל המקרים.
ואחרי שמצאנו פתרון שעובד בכל המקרים האפשריים, עכשיו האתר יבדוק, האם יש דרך יותר יעילה עם פחות פעולות (סיבוכיות זמן ריצה) ופחות משאבי מערכת, שפותרת את הבעיה.
מהו השלב הראשון בלפתור שאלות בליטקוד?
השלב הראשון כמובן, הוא להבין את השאלה. כדאי מאוד להבין בדיוק מה שאלו אותנו ולא לרוץ לפתור את השאלה. כי זה מגדיל באופן דרמטי את הסיכוי לטעות. וככל שלבן אדם יותר רע מכך שהוא מרגיש לא מספיק חכם, ככה הוא פחות ירצה להבין את השאלה וככה כנראה שהוא יתן תשובה לא נכונה וככה כנראה שהוא עוד יותר ירגיש לא חכם וחוזר חלילה.
לכן, שלב ראשון, נסה להבין את השאלה.
מה לעשות עם שאלות שאינן מובנות?
לנסות להבין אותן. חלק מהקושי בלפתור שאלות ליטקוד, הוא להבין את השאלות. כי גם לדעת לשאול שאלות בצורה ברורה, גם את זה צריך לדעת. ולא תמיד כותב השאלה, יודע לשאול את השאלה בצורה ברורה. אבל כמובן שזאת בעיה שלך ולא של השואל. כי בעולם האמיתי, הרבה פעמים תקבל בעיות לא ברורות וצריך מאמץ להבין את השאלה ואת הבעיה, לא פחות מאשר להבין איך לפתור את השאלה. לכן, תתאמץ להבין את השאלה, גם אם היא לא ברורה.
ואם אתה בראיון עבודה ונתקל בשאלה שלא ברורה לך, אז תסביר בקול למראיין, מה כן ברור לך מהשאלה ומה לא ברור לך ומה האפשרויות שאתה רואה להבין את השאלה ומה הפתרונות האפשריים לכל אחד מהפירושים האפשריים שיש לך לשאלה. כי בראיון, מנסים בעיקר להבין איך אתה רגיל לחשוב.
כמובן שבאתר ליטקוד זה לא יעבוד, אלא תצטרך להריץ פתרון והאתר יגיד לך אם לדעתו עברת את כל מקרי הבדיקה שלו או לא, בלי קשר לאם הבנת את השאלה או לא.
איך לפתור שאלת LeetCode אחרי שנראה לך שהבנת אותה?
לפתור באופן מילולי ולא תכנותי
כאשר באים לפתור שאלת ליטקוד באתר ליטקוד, יש לנו כמה אתגרים לעבור. 1 - להבין את השאלה. 2 - להבין את הפתרון באופן כללי. 3 - לכתוב, להריץ ולבדוק את הפתרון במערכת של האתר ליטקוד.
ואני אסביר: הרבה מתכנים חושבים, שהשלב הבא אחרי שמבינים שאלת ליטקוד, זה להתחיל לקודד או להתחיל לחשוב על איזה קוד יודע לבצע את הפתרון שהם רוצים לבצע.
והתהליך הזה הוא מורכב מכמה חלקים. חלק 1 - הוא להבין את הלוגיקה של הפתרון שרוצים לכתוב. חלק 2 - הוא לדעת איך לכתוב את הלוגיקה הזאת בשפת התכנות שאנחנו רוצים לכתוב בה את הפתרון. כי הרבה פעמים המגבלה של המתכנת, היא שהוא חושב דרך השפה שהוא מנסה לתכנת בה ולא בצורה מופשטת וכללית יותר.
ונכון שבסוף צריך איכשהו לקודד את הפתרון בשפה כלשהי עם מגבלות כלשהן, אבל כאשר מנסים למצוא פתרון לשאלת ליטקוד, צריכים לחשוב באופן מופשט, בלי שום אילוץ של שפה כלשהי. דהיינו, דמיין שיש לך שפת תכנות, שבה המחשב עושה בדיוק את כל מה שאתה אומר לו לעשות. אבל אך ורק את מה שאתה אומר לו לעשות, בדיוק, לא פחות ולא יותר. כל מה שתגיד לו לעשות הוא יעשה, בלי הגבלות של שפה. אם זה היה המצב, מה ואיך היית פותר את הבעיה באמצעות הרובוט?
רק כמובן שעליך לזכור, שהרובוט הוא מטומטם והוא לא יודע לחשוב בכלל. לכן אתה לא יכול להגיד לרובוט הנחיות מורכבות כגון תמיין לי את הרשימה. כי הוא לא יודע מה ואיך למיין.
לצורך העניין תדמיין שיש לך עבד שיודע להבין את הפקודות שלך ועושה את כל מה שתגיד לו. אבל הוא לא יודע לחשוב ולא יודע להבין כלום ושום דבר, אלא רק את הפעולות הבסיסיות ביותר שאינן דורשות חשיבה כלשהי. האם אתה יודע איך להסביר לאותו עבד איך לפתור את הבעיה? אם לא, אז כמובן שלא תדע איך לפתור אותה בשפת קוד כלשהי.
עכשיו נסה לחשוב שאתה משלם לעבד שלך כסף על כל דקה שהוא עובד, על כל טיפת זיעה שהוא מזיע ועל כל מאמץ שהוא מתאמץ. האם ואיך היית חוסך את הפעולות שלו ואת המאמץ שלו? זה המפתח להבין איך לייעל את הפתרון.
או במילים אחרות, נסה לחשוב על הפתרון, בצורה שאינה תלוית שפה כלשהי. נסה למצוא ילד, תסביר לו את השאלה, ואת הפעולות שהוא צריך לעשות כדי לפתור את השאלה. הילד לא יודע לחשוב על מה שלא הסברת לו, אבל בהנחה שהוא יעשה בדיוק את מה שתסביר לו, האם הוא יצליח לפתור את הבעיה?
ועכשיו נסביר יותר לעומק על
תהליכים בפתרון שאלות ליטקוד
לחלק לחלקים
אז יש כאן כמה עקרונות, העיקרון המרכזי הוא, לדעת לחלק לחלקים כל חלק מהשאלה שמוצגת לך. דהיינו, נניח שאומרים לך למצוא בחדר חתול לבן. אז יש כאן כמה תהליכים, 1 - לדעת לזהות חתול. 2 - לדעת לזהות צבע לבן. 3 - לדעת לזהות חתול לבן. אם תנסה למצוא חתול לבן, בלי שאתה יודע לזהות צבע לבן או חתול, כנראה שתהיה בבעיה. זה נקרא לחלק לחלקים ואני אנסה לתת דוגמאות בהמשך לפתרון בעיות אמיתיות מ LeetCode.
ואחרי שחילקת את השאלה לחלקים, קח כל חלק בפני עצמו ותנסה לפתור אותו בפני עצמו. ואם לא הצלחת, נסה שוב לחלק אותו לחלקים יותר קטנים. ובמהות, נסה לראות את השאלה הגדולה, כאוסף של שאלות קטנות שמחוברות אחת לשניה.
למצוא את החלק הפשוט ביותר והקטן ביותר
כאשר אתה מחלק לחלקים, בדרך כלל יעזור קודם כל לנסות לפתור את המקרה הפשוט ביותר והקטן ביותר. לדוגמא, נניח שאומרים לך למיין מערך של N איברים. המקרה הפשוט ביותר, הוא למיין מערך של איבר 1. המקרה היותר מורכב, הוא של 2 איברים. אחר כך של 3 איברים וכן הלאה, עד למקרה הכללי של N איברים.
ומהות האמירה שלי היא, שכדי לפתור שאלות מורכבות, תנסה להיות מטומטם ותנסה ללכת למקרה הכי פשוט שאתה יכול להעלות על דעתך ולפתור קודם כל אותו. את המקרה הפשוט ביותר שאתה מסוגל למצוא.
או במילים אחרות, נסה למצוא את החלק הקטן ביותר והפשוט ביותר שאתה מסוגל למצוא ותתחיל ממנו.
מה בטוח נכון
אחרי שאנחנו מחלקים את השאלה לחלקים שונים ומשונים, עכשיו עלינו לשאול, האם בין כל השאלות הקטנות שעומדות בפנינו, האם יש שאלה שאנחנו חושבים שיש לנו תשובה לשאלה הזאת, אבל שהתשובה הזאת נכונה במאה אחוז? האם יש לנו מקרה פשוט ביותר, שהפתרון שלו הוא בטוח נכון לדעתינו?
חפש את מה שנראה לך בטוח נכון. או את מה שנראה לך ביותר סיכוי להיות בטוח נכון. לאחר מכן לאט לאט, שאר החלקים יפתרו מעצמם. כי מה שלא בטוח נכון, תלוי בגורמים קטנים, שהם לכשעצמם בטוח נכונים.
איך לדעת מה בטוח נכון? איך למצוא את החלק הקטן שהוא בטוח נכון?
תשובה: לפני שמנסים למצוא מה בטוח נכון, צריכים לנסות להבין באופן כללי את החוקיות של התהליך שאנחנו מנסים לפתור אותו באופן כללי, כמו שניתן לראות בדוגמאות שאני אביא בהמשך.
או במילים אחרות, קודם כל לנסות להבין את החוקיות של התהליך שאנחנו מנסים לפתור ורק אחר כך לנסות להבין מה בטוח נכון.
איך להבין חוקיות של תהליך?
צריכים לקחת את התהליך ולחלק אותו לחלקים הכי קטנים, לתהליכים הכי פשוטים ולנסות למצוא חוקיות כלשהי, דברים שחוזרים על עצמם, במקרים הכי פשוטים, הכי קלים. ככה מוצאים חוקיות של דברים.
וכאשר באים למצוא חוקיות של דברים, צריכים לחשוב קודם כל על המקרים הפשוטים ביותר והנפוצים ביותר והקלים ביותר. דהיינו, לא לנסות להבין את החוקיות בכל המקרים האפשריים או בכל מקרי הקצה וכיו"ב.
אלא כן צריכים למצוא חוקיות כלשהי במקרים הפשוטים ביותר, במקרים הקלים ביותר, הנפוצים ביותר. ורק אחר כך לנסות ללטש את החוקיות לנוסחה יותר מדוייקת.
וחוקיות פירושה, דברים שחוזרים על עצמם, דפוסים שחוזרים על עצמם. ושוב, כפי שניתן לראות בדוגמאות שאני אביא בהמשך.
אז, אני חוזר ומדגיש, רק אחרי שמוצאים חוקיות של המקרים הפשוטים ביותר, רק אז לנסות למצוא חוקיות של מקרים יותר מורכבים.
ואז אחרי שמבינים את החוקיות של התהליך, אז לנסות למצוא את המקרה הפשוט ביותר שבטוח נכון, בהתאם לחוקיות שמצאנו אותה קודם לכן.
ומה לעשות אם אין שום דבר שהוא בטוח נכון?
אז עלינו לחפש משהו שהוא יותר נכון מדברים אחרים ולהתחיל ממנו. דהיינו: בטוח נכון פירושו, שאנחנו בטוחים שבמקרה X, התשובה היא A. אבל אם אין שום דבר שהוא בטוח נכון בצורה הזאת, אולי יש משהו שהוא בטוח נכון יותר מדברים אחרים.
דהיינו, לדוגמא שיש מקרה X שבטוח נכון שהתשובה שלו היא A או B. וזה יותר בטוח ממקרה Y שהתשובה שלו היא A או B או C. ובמקרה כזה, נעדיף להתחיל מלנסות להבין את X ולא את Y. כי X יותר בטוח מאשר Y.
דהיינו, במקום לחפש מה בטוח נכון, נחפש מה יותר בטוח. נחפש את נקודת הוודאות היחסית שאנחנו יכולים למצוא.
פתרון שעובד בכל מצב
כאשר יש לך נוסחא לפתרון כלשהו, שאל את עצמך, האם אתה בטוח במאה אחוז שתמיד בכל קלט שתקבל, תמיד הנוסחא שלך תעבוד? אתה באמת בטוח בזה? האם זה בהכרח נכון? למה זה בהכרח יעבוד לא משנה מה? כך, תוכל לאתר מקרי קצה שבהם הקוד שלך לא יעבוד. וככה תתקרב לפתרון הכללי שעובד תמיד.
יעילות זמן ריצה / סיבוכיות זמן ריצה
וכמובן לפני שאתה מנסה לפתור את השאלה בדרך היעילה ביותר או לפני שאתה מנסה לייעל את פתרון השאלה, קודם כל תנסה לפתור את השאלה בצורה כלשהי, גם אם היא לא יעילה. כי יותר קל לפתור שאלות בצורה לא יעילה מאשר בצורה הכי יעילה. ולכן צריכים להתחיל בצורה קלה, דהיינו, לפתור את השאלות בצורה כלשהי, לפני שמנסים לייעל את התהליך.
איך לייעל זמן ריצה?
בעיקרון יעול זמן הריצה, מתבצע באמצעות שינוי בלוגיקה של הפתרון. ובמהות של ההתייעלות, זה לנסות לעבור על התהליך הלא יעיל כולו מהתחלה עד הסוף ועל כל פעולה, לשאול, האם אני חושב שיש אפשרות לחסוך איכשהו את הפעולה הזאת? מה הפעולה הזאת מנסה להשיג? אולי יש דרך יותר קצרה להשיג את אותה התכלית של הפעולה? אולי ניתן להסיק דבר מתוך דבר? אולי ניתן לעשות סימן כלשהו שיחסוך לנו פעולות כלשהן?
במהות, נסה לעבור פעולה פעולה בפני עצמה. נסה להבין את תכליתה ואולי יש דרך לדלג עליה איכשהו? אולי ניתן להסיק אותה ממשהו אחר? האם ואולי יש פעולות שחוזרות על עצמן? האם יש פעולות שמרגישות לך מיותרות, נסה לחסוך אותן.
לסיכום
שלב 1 - תהיה בטוח שהבנת את השאלה
שלב 2 - נסה לפתור את השאלה בלי קשר לשפת תכנות כלשהי
שלב 3 - תחלק את השאלה לחלקים, כמה שיותר קטנים
שלב 4 - נסה למצוא את החלק הקטן ביותר ואת השאלה הפשוטה ביותר שאתה יכול למצוא
שלב 5 - נסה להבין באופן כללי את החוקיות של התהליך שאותו אתה מנסה לפצח
שלב 6 - נסה לחפש משהו שהוא בטוח נכון / נסה לחפש מצב שאתה חושב שיש לך אליו פתרון כלשהו שהוא בטוח נכון
שלב 7 - נסה לפתור את השאלה בדרך כלשהי, גם אם היא לא יעילה
שלב 8 - נסה להבין האם הפתרון שלך עובד בכל המקרים
שלב 9 - נסה לייעל את התהליך, באמצעות לייתר פעולות מיותרות וכיוב
בהצלחה
ליטקוד, זה שם של אתר אינטרנט, שמציג שאלות מראיונות עבודה למשרות של פיתוח תוכנה ותכנות. בעיות שונות בכתיבת קוד וכיו"ב. לפי רמות קושי / נושאים וכולי.
בעולם המתכנתים מקובל לומר ש "מי שמלטקד לא מפחד". דהיינו, מי שרגיל לפתור שאלות ליטקוד, לא מפחד מראיונות עבודה.
בפועל אנשים שרוצים לעבוד בהייטק במשרות של פיתוח, בדרך כלל הם יתרגלו שאלות ליטקוד, כדי להתכונן לראיונות עבודה.
למה לפתור שאלות ליטקוד?
1 - כי זה יגרום לך להיות יותר חכם וזה יעזור לך בכל תחומי החיים. 2 - כי זה כיף לאמץ את המוח וזאת הנאה שכלית שמי שיש לו שכל אז יודע שזה כיף לאתגר את המוח, כי יש לזה "טעם של שכל" (פילוסופיה / אהבת החוכמה).
3 - אם אתה מחפש עבודה בהייטק, אז זה יעזור לך להתקבל לעבודה הנחשקת. וכמובן שזה יעזור לך גם לשרוד את העבודה ולא רק להתקבל אליה. אבל זה כבר כפועל יוצא של זה שיש לך יותר שכל.
בנוסף חשוב מאוד לציין, כי שאלות ליטקוד, הן הזדמנות לפתח את החשיבה באופן מדוייק. ויש להן יתרון על פני מאמץ שכלי בתחומים אחרים. כי בליטקוד, יש בעיות מוגדרות וספציפיות, עם מערכת שבודקת בדיוק את הפתרון שלך, האם באמת הוא עובד וכמה הוא יעיל וכולי. ואז זה מגדיל את הסיכוי, שאתה לא בטעות תחשוב שאתה חכם, אלא באמת תהיה חכם. וזה תודות למנגנון הבדיקה של 0 או 1, שבודק בדיוק האם פתרת נכון או שלא.
מה זה אומר לפתור בעיה בליטקוד?
אז כשבאים לפתור בעיה בליטקוד, יש כמה עקרונות שהמערכת בודקת. 1 - האם פתרנו את הבעיה שהוצגה. 2 - האם ומהי היעילות אלגוריתמית, דהיינו: מהי היעילות (סיבוכיות זמן הריצה) של הפתרון שפתרנו את הבעיה. דהיינו, כמה פעולות היינו צריכים לבצע, ביחס לכמות המידע שנתנו לנו לנתח (ע"ע מה זה זמן ריצה). וגם מהי היעילות של משאבי המחשב / משאבי הזיכרון (סיבוכיות מקום) שהשתמשנו בהם כדי לפתור את הבעיה.
מה זה אומר שפתרנו את השאלה?
אז לפתור את השאלה, אפשרי באופן חלקי או באופן מלא. וזה כמובן בלי קשר ליעילות של הפתרון. ולפתור שאלה באופן חלקי, זה אומר שהפתרון אכן יפתור מצבים מסויימים של השאלה. אבל פתרון מלא של השאלה, הוא רק כאשר הפתרון שהצענו לפתור את השאלה, יפתור אותה בכל המצבים האפשריים שהאתר LeetCode יבדוק את הפתרון שלנו.
כי בצוות של האתר ליטקוד, יש אנשים שלוקחים פתרונות של אנשים ומנסים להקריס את הפתרונות האלו בכל מיני מקרה קצה כאלו ואחרים. ולפתור את השאלה מבחינת ליטקוד, זה רק כאשר הפתרון שלנו עובר את כל מצבי הבדיקה TestCase שהם הגדירו לבדוק את הפתרון שלנו.
או במילים אחרות, זאת לא רק חוכמה לדעת לפתור שאלות בליטקוד, אלא זאת גם חוכמה להבין איך לפתור את השאלה בכל מצב אפשרי. וזאת גם חוכמה להבין על כל פתרון, האם ובאילו מצבים הוא לא יפתור את השאלה. דהיינו, להבדיל בין פתרון אפשרי, שרק אפשרי שהוא יעבוד בחלק מהמקרים, לבין פתרון מחוייב, שמחוייב שהוא יעבוד בכל המקרים.
ואחרי שמצאנו פתרון שעובד בכל המקרים האפשריים, עכשיו האתר יבדוק, האם יש דרך יותר יעילה עם פחות פעולות (סיבוכיות זמן ריצה) ופחות משאבי מערכת, שפותרת את הבעיה.
מהו השלב הראשון בלפתור שאלות בליטקוד?
השלב הראשון כמובן, הוא להבין את השאלה. כדאי מאוד להבין בדיוק מה שאלו אותנו ולא לרוץ לפתור את השאלה. כי זה מגדיל באופן דרמטי את הסיכוי לטעות. וככל שלבן אדם יותר רע מכך שהוא מרגיש לא מספיק חכם, ככה הוא פחות ירצה להבין את השאלה וככה כנראה שהוא יתן תשובה לא נכונה וככה כנראה שהוא עוד יותר ירגיש לא חכם וחוזר חלילה.
לכן, שלב ראשון, נסה להבין את השאלה.
מה לעשות עם שאלות שאינן מובנות?
לנסות להבין אותן. חלק מהקושי בלפתור שאלות ליטקוד, הוא להבין את השאלות. כי גם לדעת לשאול שאלות בצורה ברורה, גם את זה צריך לדעת. ולא תמיד כותב השאלה, יודע לשאול את השאלה בצורה ברורה. אבל כמובן שזאת בעיה שלך ולא של השואל. כי בעולם האמיתי, הרבה פעמים תקבל בעיות לא ברורות וצריך מאמץ להבין את השאלה ואת הבעיה, לא פחות מאשר להבין איך לפתור את השאלה. לכן, תתאמץ להבין את השאלה, גם אם היא לא ברורה.
ואם אתה בראיון עבודה ונתקל בשאלה שלא ברורה לך, אז תסביר בקול למראיין, מה כן ברור לך מהשאלה ומה לא ברור לך ומה האפשרויות שאתה רואה להבין את השאלה ומה הפתרונות האפשריים לכל אחד מהפירושים האפשריים שיש לך לשאלה. כי בראיון, מנסים בעיקר להבין איך אתה רגיל לחשוב.
כמובן שבאתר ליטקוד זה לא יעבוד, אלא תצטרך להריץ פתרון והאתר יגיד לך אם לדעתו עברת את כל מקרי הבדיקה שלו או לא, בלי קשר לאם הבנת את השאלה או לא.
איך לפתור שאלת LeetCode אחרי שנראה לך שהבנת אותה?
לפתור באופן מילולי ולא תכנותי
כאשר באים לפתור שאלת ליטקוד באתר ליטקוד, יש לנו כמה אתגרים לעבור. 1 - להבין את השאלה. 2 - להבין את הפתרון באופן כללי. 3 - לכתוב, להריץ ולבדוק את הפתרון במערכת של האתר ליטקוד.
ואני אסביר: הרבה מתכנים חושבים, שהשלב הבא אחרי שמבינים שאלת ליטקוד, זה להתחיל לקודד או להתחיל לחשוב על איזה קוד יודע לבצע את הפתרון שהם רוצים לבצע.
והתהליך הזה הוא מורכב מכמה חלקים. חלק 1 - הוא להבין את הלוגיקה של הפתרון שרוצים לכתוב. חלק 2 - הוא לדעת איך לכתוב את הלוגיקה הזאת בשפת התכנות שאנחנו רוצים לכתוב בה את הפתרון. כי הרבה פעמים המגבלה של המתכנת, היא שהוא חושב דרך השפה שהוא מנסה לתכנת בה ולא בצורה מופשטת וכללית יותר.
ונכון שבסוף צריך איכשהו לקודד את הפתרון בשפה כלשהי עם מגבלות כלשהן, אבל כאשר מנסים למצוא פתרון לשאלת ליטקוד, צריכים לחשוב באופן מופשט, בלי שום אילוץ של שפה כלשהי. דהיינו, דמיין שיש לך שפת תכנות, שבה המחשב עושה בדיוק את כל מה שאתה אומר לו לעשות. אבל אך ורק את מה שאתה אומר לו לעשות, בדיוק, לא פחות ולא יותר. כל מה שתגיד לו לעשות הוא יעשה, בלי הגבלות של שפה. אם זה היה המצב, מה ואיך היית פותר את הבעיה באמצעות הרובוט?
רק כמובן שעליך לזכור, שהרובוט הוא מטומטם והוא לא יודע לחשוב בכלל. לכן אתה לא יכול להגיד לרובוט הנחיות מורכבות כגון תמיין לי את הרשימה. כי הוא לא יודע מה ואיך למיין.
לצורך העניין תדמיין שיש לך עבד שיודע להבין את הפקודות שלך ועושה את כל מה שתגיד לו. אבל הוא לא יודע לחשוב ולא יודע להבין כלום ושום דבר, אלא רק את הפעולות הבסיסיות ביותר שאינן דורשות חשיבה כלשהי. האם אתה יודע איך להסביר לאותו עבד איך לפתור את הבעיה? אם לא, אז כמובן שלא תדע איך לפתור אותה בשפת קוד כלשהי.
עכשיו נסה לחשוב שאתה משלם לעבד שלך כסף על כל דקה שהוא עובד, על כל טיפת זיעה שהוא מזיע ועל כל מאמץ שהוא מתאמץ. האם ואיך היית חוסך את הפעולות שלו ואת המאמץ שלו? זה המפתח להבין איך לייעל את הפתרון.
או במילים אחרות, נסה לחשוב על הפתרון, בצורה שאינה תלוית שפה כלשהי. נסה למצוא ילד, תסביר לו את השאלה, ואת הפעולות שהוא צריך לעשות כדי לפתור את השאלה. הילד לא יודע לחשוב על מה שלא הסברת לו, אבל בהנחה שהוא יעשה בדיוק את מה שתסביר לו, האם הוא יצליח לפתור את הבעיה?
ועכשיו נסביר יותר לעומק על
תהליכים בפתרון שאלות ליטקוד
לחלק לחלקים
אז יש כאן כמה עקרונות, העיקרון המרכזי הוא, לדעת לחלק לחלקים כל חלק מהשאלה שמוצגת לך. דהיינו, נניח שאומרים לך למצוא בחדר חתול לבן. אז יש כאן כמה תהליכים, 1 - לדעת לזהות חתול. 2 - לדעת לזהות צבע לבן. 3 - לדעת לזהות חתול לבן. אם תנסה למצוא חתול לבן, בלי שאתה יודע לזהות צבע לבן או חתול, כנראה שתהיה בבעיה. זה נקרא לחלק לחלקים ואני אנסה לתת דוגמאות בהמשך לפתרון בעיות אמיתיות מ LeetCode.
ואחרי שחילקת את השאלה לחלקים, קח כל חלק בפני עצמו ותנסה לפתור אותו בפני עצמו. ואם לא הצלחת, נסה שוב לחלק אותו לחלקים יותר קטנים. ובמהות, נסה לראות את השאלה הגדולה, כאוסף של שאלות קטנות שמחוברות אחת לשניה.
למצוא את החלק הפשוט ביותר והקטן ביותר
כאשר אתה מחלק לחלקים, בדרך כלל יעזור קודם כל לנסות לפתור את המקרה הפשוט ביותר והקטן ביותר. לדוגמא, נניח שאומרים לך למיין מערך של N איברים. המקרה הפשוט ביותר, הוא למיין מערך של איבר 1. המקרה היותר מורכב, הוא של 2 איברים. אחר כך של 3 איברים וכן הלאה, עד למקרה הכללי של N איברים.
ומהות האמירה שלי היא, שכדי לפתור שאלות מורכבות, תנסה להיות מטומטם ותנסה ללכת למקרה הכי פשוט שאתה יכול להעלות על דעתך ולפתור קודם כל אותו. את המקרה הפשוט ביותר שאתה מסוגל למצוא.
או במילים אחרות, נסה למצוא את החלק הקטן ביותר והפשוט ביותר שאתה מסוגל למצוא ותתחיל ממנו.
מה בטוח נכון
אחרי שאנחנו מחלקים את השאלה לחלקים שונים ומשונים, עכשיו עלינו לשאול, האם בין כל השאלות הקטנות שעומדות בפנינו, האם יש שאלה שאנחנו חושבים שיש לנו תשובה לשאלה הזאת, אבל שהתשובה הזאת נכונה במאה אחוז? האם יש לנו מקרה פשוט ביותר, שהפתרון שלו הוא בטוח נכון לדעתינו?
חפש את מה שנראה לך בטוח נכון. או את מה שנראה לך ביותר סיכוי להיות בטוח נכון. לאחר מכן לאט לאט, שאר החלקים יפתרו מעצמם. כי מה שלא בטוח נכון, תלוי בגורמים קטנים, שהם לכשעצמם בטוח נכונים.
איך לדעת מה בטוח נכון? איך למצוא את החלק הקטן שהוא בטוח נכון?
תשובה: לפני שמנסים למצוא מה בטוח נכון, צריכים לנסות להבין באופן כללי את החוקיות של התהליך שאנחנו מנסים לפתור אותו באופן כללי, כמו שניתן לראות בדוגמאות שאני אביא בהמשך.
או במילים אחרות, קודם כל לנסות להבין את החוקיות של התהליך שאנחנו מנסים לפתור ורק אחר כך לנסות להבין מה בטוח נכון.
איך להבין חוקיות של תהליך?
צריכים לקחת את התהליך ולחלק אותו לחלקים הכי קטנים, לתהליכים הכי פשוטים ולנסות למצוא חוקיות כלשהי, דברים שחוזרים על עצמם, במקרים הכי פשוטים, הכי קלים. ככה מוצאים חוקיות של דברים.
וכאשר באים למצוא חוקיות של דברים, צריכים לחשוב קודם כל על המקרים הפשוטים ביותר והנפוצים ביותר והקלים ביותר. דהיינו, לא לנסות להבין את החוקיות בכל המקרים האפשריים או בכל מקרי הקצה וכיו"ב.
אלא כן צריכים למצוא חוקיות כלשהי במקרים הפשוטים ביותר, במקרים הקלים ביותר, הנפוצים ביותר. ורק אחר כך לנסות ללטש את החוקיות לנוסחה יותר מדוייקת.
וחוקיות פירושה, דברים שחוזרים על עצמם, דפוסים שחוזרים על עצמם. ושוב, כפי שניתן לראות בדוגמאות שאני אביא בהמשך.
אז, אני חוזר ומדגיש, רק אחרי שמוצאים חוקיות של המקרים הפשוטים ביותר, רק אז לנסות למצוא חוקיות של מקרים יותר מורכבים.
ואז אחרי שמבינים את החוקיות של התהליך, אז לנסות למצוא את המקרה הפשוט ביותר שבטוח נכון, בהתאם לחוקיות שמצאנו אותה קודם לכן.
ומה לעשות אם אין שום דבר שהוא בטוח נכון?
אז עלינו לחפש משהו שהוא יותר נכון מדברים אחרים ולהתחיל ממנו. דהיינו: בטוח נכון פירושו, שאנחנו בטוחים שבמקרה X, התשובה היא A. אבל אם אין שום דבר שהוא בטוח נכון בצורה הזאת, אולי יש משהו שהוא בטוח נכון יותר מדברים אחרים.
דהיינו, לדוגמא שיש מקרה X שבטוח נכון שהתשובה שלו היא A או B. וזה יותר בטוח ממקרה Y שהתשובה שלו היא A או B או C. ובמקרה כזה, נעדיף להתחיל מלנסות להבין את X ולא את Y. כי X יותר בטוח מאשר Y.
דהיינו, במקום לחפש מה בטוח נכון, נחפש מה יותר בטוח. נחפש את נקודת הוודאות היחסית שאנחנו יכולים למצוא.
פתרון שעובד בכל מצב
כאשר יש לך נוסחא לפתרון כלשהו, שאל את עצמך, האם אתה בטוח במאה אחוז שתמיד בכל קלט שתקבל, תמיד הנוסחא שלך תעבוד? אתה באמת בטוח בזה? האם זה בהכרח נכון? למה זה בהכרח יעבוד לא משנה מה? כך, תוכל לאתר מקרי קצה שבהם הקוד שלך לא יעבוד. וככה תתקרב לפתרון הכללי שעובד תמיד.
יעילות זמן ריצה / סיבוכיות זמן ריצה
וכמובן לפני שאתה מנסה לפתור את השאלה בדרך היעילה ביותר או לפני שאתה מנסה לייעל את פתרון השאלה, קודם כל תנסה לפתור את השאלה בצורה כלשהי, גם אם היא לא יעילה. כי יותר קל לפתור שאלות בצורה לא יעילה מאשר בצורה הכי יעילה. ולכן צריכים להתחיל בצורה קלה, דהיינו, לפתור את השאלות בצורה כלשהי, לפני שמנסים לייעל את התהליך.
איך לייעל זמן ריצה?
בעיקרון יעול זמן הריצה, מתבצע באמצעות שינוי בלוגיקה של הפתרון. ובמהות של ההתייעלות, זה לנסות לעבור על התהליך הלא יעיל כולו מהתחלה עד הסוף ועל כל פעולה, לשאול, האם אני חושב שיש אפשרות לחסוך איכשהו את הפעולה הזאת? מה הפעולה הזאת מנסה להשיג? אולי יש דרך יותר קצרה להשיג את אותה התכלית של הפעולה? אולי ניתן להסיק דבר מתוך דבר? אולי ניתן לעשות סימן כלשהו שיחסוך לנו פעולות כלשהן?
במהות, נסה לעבור פעולה פעולה בפני עצמה. נסה להבין את תכליתה ואולי יש דרך לדלג עליה איכשהו? אולי ניתן להסיק אותה ממשהו אחר? האם ואולי יש פעולות שחוזרות על עצמן? האם יש פעולות שמרגישות לך מיותרות, נסה לחסוך אותן.
לסיכום
שלב 1 - תהיה בטוח שהבנת את השאלה
שלב 2 - נסה לפתור את השאלה בלי קשר לשפת תכנות כלשהי
שלב 3 - תחלק את השאלה לחלקים, כמה שיותר קטנים
שלב 4 - נסה למצוא את החלק הקטן ביותר ואת השאלה הפשוטה ביותר שאתה יכול למצוא
שלב 5 - נסה להבין באופן כללי את החוקיות של התהליך שאותו אתה מנסה לפצח
שלב 6 - נסה לחפש משהו שהוא בטוח נכון / נסה לחפש מצב שאתה חושב שיש לך אליו פתרון כלשהו שהוא בטוח נכון
שלב 7 - נסה לפתור את השאלה בדרך כלשהי, גם אם היא לא יעילה
שלב 8 - נסה להבין האם הפתרון שלך עובד בכל המקרים
שלב 9 - נסה לייעל את התהליך, באמצעות לייתר פעולות מיותרות וכיוב
בהצלחה