Leetcode 刷題 pattern - 一週年特典


Posted by Po-Jen on 2020-07-05

前言

自從去年開始寫 Leetcode 刷題 pattern,到現在默默地也累積了 11 篇,看著越來越長的列表,心裡說不爽是騙人的哈哈,其中有些我覺得寫得不錯,但有幾篇我覺得還可以再更進步,這一年的累積讓我發現一些事情。所以想藉由一週年的時刻反思,分享歷程中的兩點心得,也讓大家參考參考。

第一天心態 v.s. 第二天心態

這系列我第一篇寫的是 Two Pointer,也是我印象最深刻的一篇,原因是我寫得很開心 XD。

也許是因為我當時才剛剛開始應用 pattern 的方式開始刷題,又或許是因為第一次寫這種整理式的 Leetcode 文章,過程非常有趣,像在玩一樣,根本不想停,很想用生動活潑的方式把我腦海中活靈活現的演算法呈現出來,所以我盡可能寫得好笑、並把所有觀念一步步解釋清楚。放四個範例也是精挑細選,覺得剛剛好。寫完還忍不住分享到 FB 和一畝三分地。

但隨著每個月一篇發下來,我發現我自己逐漸喪失第一篇的熱情,後來的心態變成 - "嗯,這次要寫什麼 pattern 呢?放三個範例應該就夠了吧?"。我直接沿用了之前寫作的形式,然後機械式地完成。

我隱約知道這樣做不太對勁,因為我在寫文章時感覺無趣,我沒有繼續投入我的靈魂,但我不確定我該怎麼跳出這種狀態,直到前陣子讀了 "貝佐斯寫給股東的信:亞馬遜 14 條成長法則帶你事業、人生一起飛",才讓我頓悟自己的問題。這本書的第 14 章,正是在探討 Amazon 的一個重要法則 - "永遠保持第一天心態"。Jeff Bezos 的一句話精準點破了我的困境,他說:"第二天意味著停滯,繼而變得無足輕重,繼而痛苦地衰退,最終就是死亡。這就是為什麼我總是強調要保持第一天心態的原因"。

我看到這句話頓時清醒過來,因為完全被戳中(心中最軟的一塊),可惜當我著急地往後翻,這本書卻沒回答我當下最渴望的問題 - 那該怎麼辦?,因為 Amazon 的方法是永遠把顧客放在第一位,就像一個沒有顧客就沒有明天的新創公司,但這沒辦法解決我的問題,難道我要懇求讀者酸一波我寫得不夠好的地方嗎 XD

所以我開始探索該怎麼永遠保持第一天,我不知道怎麼做,所以我從閒暇時光開始。休閒時,我逐漸放棄跟隨腦袋建立的套路(不直接去做以前的嗜好),而是更多去傾聽自己內心的聲音,想做什麼就做,盡可能隨心去體驗。我發現自己一直很想學習怎麼入門交響樂,所以就上 Youtube 找找看,隨意瀏覽,結果從 走進交響樂影片的 6:49 到 8:31 體驗到調的美妙(幾個音的排列組合變化,居然能造出不同國家的民族曲調!),覺得音樂好美好神奇。

看完交響樂的東東,又發現自己一直有點害怕藝術史,也不太懂怎麼欣賞藝術,所以我也上網找資源,結果我從 4 個大魔王,200 秒帶你入門極簡藝術史 發現由三個影響超大的藝術家,可以很有感地切入原本覺得像一團散沙的藝術史(還順便看了幽默業配哈哈哈)。然後從 藝術很難嗎 第三季 16 杜尚:一個小便池是怎麼顛覆了藝術史? 感受到自己看待藝術的方式被解放了,不再需要逼自己學習專家的欣賞法,藝術的本質就應該要能打動人心,管這作品多有名,如果我沒被打動,那就不適合當下的我,不需要覺得是自己不懂欣賞或需要學習什麼。

在探索的過程中,我也開始練習,如果我發現某件事情我不想再做,我就立刻停掉,忽略腦海裡面那個覺得,既然做了就要把它做完的聲音(我甚至不知道自己從何時養成這種恐懼,怕自己開始做一件事沒有做完就表示沒有恆心,但這根本是莫名其妙不能一體適用的結論,有時克服無趣是必要的,但有時不是!如果覺得不對勁,放下又有什麼關係,為什麼要自己給自己壓力!)

而這項練習到現在,就讓我在此時捨棄了這週原本要繼續寫的 leetcode pattern,停下腳步來思考自己此時最在意什麼、最想跟讀者們分享什麼,這使得現在在寫這篇文章的我,覺得充滿意義。

我也邀請大家思考一下,你的生活中是否已經有很多事情落入第二天的心態,可能是你的感情、可能是你的工作、可能是你的學業、可能是你跟家人朋友的相處,如果你覺得一成不變,如果你覺得想重新找回熱情,不妨先停一下,聽聽自己最想要什麼,暫時放下腦袋記得的習慣,做你想做的,而不是做你該做的。然後你可能也會慢慢發現,原來該做的事,也可能透過重新探索,變成你想做的事 (就像我眼前的這篇文章原本已經變成我該做的例行公事,但我透過把它變成 梗圖競技生死鬥 一週年紀念心得,我現在寫起來可又 high 了!)。

Pattern 跟演繹歸納的平衡

在掌握到 leetcode pattern 的刷題方法前,我習慣的思考模式是演繹 -> 歸納 -> 演繹 -> 歸納(簡稱為演繹 -> 歸納螺旋丸),不斷迂迴深入直到想出解法。這個做法很費時,但是想出解法時,能夠形成一條,從題目到解法,一條連貫不斷的道路,這條思考的路非常容易讓人跟上,因為他是連續的。

學到 leetcode pattern 後,套用 pattern 成功的機率大幅增加,會讓我不自覺地食髓知味,於是有時候就會發生,無法套用 pattern,卻落入只想找出 pattern,無法順暢使出 "演繹 -> 歸納螺旋丸"(面試時喊出這大招名稱,好像有點太中二) 的狀態。通常陷入這種狀態,就會讓思考卡死,這也讓我在 Micorsoft 的 onsite 面試中失敗(當然還有其他因素啦)。

我後來觀察發現,使用 leetcode pattern,就像是蟲洞,直接把我從起點(題目)傳送到終點(解法),我幾乎是忽略了從起點到終點連續的路徑,跳躍式地抵達終點。但當這蟲洞在我腦海中不存在,就卡死了,因為蟲洞不是隨意可以找出來的。而且因為蟲洞的誘惑太大,我很難捨棄尋找蟲洞的衝動。

這件事情,也是很多人在刷題過程中會遭遇的問題,如果想不出解法,到底要不要看解答?畢竟看解答就像是直接學蟲洞在哪,下次直接找蟲洞。或許你可以用看解答的方法熟練解法、進而通過面試。可是,捫心自問,你真的有把演算法學通嗎?

我個人認為這不是根本的解法,根本的解法應該是,不斷體驗解決題目的路徑到融會貫通,把 "演繹 -> 歸納螺旋丸" 用到極為純熟,過程幾乎不太會卡關(不太會卡關並不代表要一直往解法逼近,而是一直可以想下去,就算暫時卡住也能很快 backtrack,不會有卡死的感覺,釐清這一點很重要),讓速度越來越快,並把走過很多次的路徑,形成一個因為已經太懂,所以可以輕鬆使用的蟲洞。

但說實話,以上的解法是理論,目前我還沒有成功驗證到演算法大成的感覺,我目前有兩個嘗試方向:

  1. 看一些有趣的演算法文章,像 fucking-algorithmDo you actually need to use std::map?,用各種不同的方式增強自己對演算法和資料結構的感受。
  2. 從簡單的題目開始慢慢寫,想不出來就擱著去寫想得出來的,一點一滴磨練 "演繹 -> 歸納螺旋丸"。關於這點,可以參考一下 Leetcode 刷題雜談 - 該如何每天都刷題

也許只是我做得還不夠,所以還沒有驗證,又或許我還沒找到最適合我的方法。

總結

今天分享了自己這一年來在 Leetcode pattern 這系列文章上獲得的體悟,在展現自己問題的同時,也在幫助自己解決我遇到的這些問題。

我希望大家可以不要放棄,如果你遇到一些問題,請不要直接下結論,覺得 "狀況就是這樣啊,本來就沒辦法"。我個人認為,這些是方便的藉口,但不是問題的本質,如果想擁有心靈充實的生活,就需要放棄這些藉口,回過頭來更了解自己,看見問題的本質,不然就只能在 "忍受問題" 或 "逃避問題",這兩個爛蘋果中二選一。

以我分享的第二天心態為例,我的問題是,我開始覺得寫這系列文章無聊,而一般常見的結論是,因為我寫了很多篇,所以喪失新鮮感,大家都會這樣,這很正常,討論結束,接下來要嘛忍住無聊繼續寫(忍受問題),要嘛就是去寫新主題(逃避問題)。但看完上面,大家都知道,其實更接近問題本質的觀察是,我會無聊,有很大一部份原因,是我只跟隨以前的套路寫文章,而忽略我當下最想寫什麼主題、想用什麼形式寫!(例如這個月很想寫某個主題,就暫停 leetcode pattern;或想試試錄一段模擬面試來分享怎麼應用 leetcode pattern,那就錄看看啊。讓事情變好玩的方法,只要打開了心,隨便都有!) 如果我能更傾聽自己的內心,是不是就會完全不一樣?這也變成我下一次實驗的方向。

為了擴展到生活的其他層面,讓我再扯遠一下,我滑 PTT 不時會看到一些文章,討論因為有了小孩,就沒顧到另一半的情緒;有些人會留言說有小孩本來就會很忙很累,這沒辦法,但真的是這樣嗎?如果靜下心想想,難道不會有各種小方法讓另一半感受到關心嗎?我覺得如果認真去想,肯定是有方法的,做起來也未必真的難(說不定你只是沒用對方最有感的方法表達愛,詳見 我的愛之語筆記,港動推),甚至可能有辦法把這過程變得很好玩,只是,我們習慣用常見的理由,放棄探索的可能性。所以啦,如果你的生活中有相似的情況,不妨停下來好好檢視一下,先把所有情緒放在一旁,觀察並理解為什麼你會處在這個狀況。

這次因為沒有放棄,才讓我有機會從看書連結回自己的問題、也才有機會在生活中練習保持第一天心態,不然這一篇文章,就會是 Leetcode 刷題 pattern - K-way merge 了(偷爆雷 XD)。

延伸閱讀

  1. Leetcode 刷題 pattern - Two Pointer
  2. Leetcode 刷題 pattern - Sliding Window
  3. Leetcode 刷題 pattern - Next Greater Element
  4. Leetcode 刷題 pattern - Fast & Slow Pointer
  5. Leetcode 刷題 pattern - Breadth-First Search
  6. Leetcode 刷題 pattern - Merge Intervals
  7. Leetcode 刷題 pattern - Cyclic Sort
  8. Leetcode 刷題 pattern - Two Heaps
  9. Leetcode 刷題 pattern - Top K elements
  10. Leetcode 刷題 pattern - Topological Sort
  11. Leetcode 刷題 pattern - Bitwise XOR

關於作者:
@pojenlai 演算法工程師,希望活在當下,看到本質


#Leetcode









Related Posts

作夢也在寫程式~讓 Siri 講睡前故事

作夢也在寫程式~讓 Siri 講睡前故事

Python Web Flask 實戰開發教學 - SQLAlchemy 與 ORM

Python Web Flask 實戰開發教學 - SQLAlchemy 與 ORM

Ceres 函式庫簡介

Ceres 函式庫簡介



Newsletter




Comments