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

淺談 React Fiber 及其對 lifecycles 造成的影響

淺談 React Fiber 及其對 lifecycles 造成的影響

如何使用 Python Tkinter 製作 GUI 應用程式入門教學

如何使用 Python Tkinter 製作 GUI 應用程式入門教學

Module 模組化概念

Module 模組化概念


Sponsored



Newsletter




Comments