記一次 Leetcode 刷題體悟 - Valid Number
前言
身在大 CS 時代,可能很多人有刷題的經驗,也可能像筆者一樣正經歷刷 Hard 題的各種撞牆。但在這種撞牆的時刻,我們反而可以來觀察自己的思考方式是不是有問題,才會導致撞牆。
今天,就讓我們一起來看一題令許多人抓狂的 valid number。
題目介紹 - Valid Number
題目敘述如下:
基本上就是要判斷一個字串是不是可以被當作一個數字。如果你試著去解解看這題,你可能會發現一件事,就是你很容易不斷漏考慮一些 case。但你不孤單,只要看看這題精美的通過率和 dislike 數就可見一班XD
但如果我們也像大家一樣覺得這題出得很爛就不想學,那就非常可惜了。因為如果你堅持下去,會看到很不一樣的風景。接下來,就讓我們一起看下去。
解法一 - 將各階段分類好漸進處理
這種題目最麻煩的地方就在於,如果沒有把規則想好,就會涵蓋不到一些 edge cases,進而為了處理這些奇怪 case 使得邏輯變得很混亂,甚至會發生修了 A bug 結果又產生 b 跟 c bug 的慘況。
所以在有模糊的概念就開始寫 code 之前,我們可以先想想合理的 case 應該要長什麼樣子,先寫出第一版的 valid pattern([] 裡面表示是 optional,類似 linux command line tool 的說明):
1 | [+/-] 數字(可以是小數) [e數字(不能是小數)] |
而不屬於這個 valid pattern 的其他字串都視為 invalid。
接下來我們可以用題目中提供的 test cases 檢視一下我們的 pattern 是否已經足夠,會發現有幾個例子沒有被涵蓋到:
- “ 0.1 “ => true (最前面跟最後面都可以有 space)
- “ 6e-1” => true (e 後面的數字可以有 +/-)
1 | [spaces][+/-]數字(可以是小數)[e[+/-]數字(不能是小數)][spaces] |
所以我們的邏輯應該要依序處理:
- Skip spaces
- Check ‘+’/‘-‘
- Check digital(can contain “.”)
- Check exponent
a. Check ‘+’/‘-‘
b. Check digital(cannot contain “.”) - Check space
這時再開始寫程式,就覺得邏輯清晰,輕舟已過萬蟲山:
1 | class Solution { |
但到這邊還沒完,我們還可以對這題挖得更加深入。
解法二 - Regular Expression
在解法一寫出合理 pattern 的時候,我就想到了 regular expression。
雖然 regular expression 的寫法我已經忘了,但從這個影片 Regular Expressions (Regex) Tutorial: How to Match Any Pattern of Text 重新學習,再參考一下相關的 討論串 ,就可以寫出一個神簡潔的程式碼 :
1 | class Solution { |
這個版本無法通過 leetcode 上的 test cases,不過我用 Sublime Text 測試時結果正確。
雖不確定是什麼問題,但現在的目的不是逼自己要把所有東西都寫對,我只是想欣賞欣賞簡潔解的美好,所以 bug 先擱著。看看這程式碼真的覺得神清氣爽。
解法三 - Deterministic Finite Automaton
基於好奇的心理,我又去翻了一下討論區,結果看到一個超猛的東西 - DFA (Deterministic Finite Automaton)。這傢伙基本上就是一個狀態機,根據你的輸入會在不同狀態間跳來跳去,所以你最後只要看有沒有跳到 valid state 就好,超酷。
1 | class Solution { |
這種解法真的有夠帥,假設你今天沒有要找工作或得把這東西學會的壓力,是不是肯定會感受到一股開心的感覺,因為被開眼界了!而不是一堆自己得學會,矮唷我怎麼想不出來等等的各種延伸情緒。
因為我之前也沒有真正學過 DFA 的理論,就不多說了,有興趣的讀者可以參考一下這兩個討論串,應該就能清楚:
- [C++] My thought with DFA
- https://leetcode.com/problems/valid-number/discuss/23798/Cleanest-C%2B%2B-Solution-using-DFA-(impress-your-interviewer-with-elegant-code!!)
總結
今天跟大家分享了一次刷 Hard 題的心路歷程,主要也是希望大家更把心情放輕鬆,享受刷題過程,畢竟人生苦短,既然有緣來刷題,不如就開開心心地學習,越寫越開心才會越寫越厲害,希望這篇文章對於正在題海中奮鬥的工程師們有些幫助。
延伸閱讀
關於作者:
@pojenlai 演算法工程師,對機器人、電腦視覺和人工智慧有少許研究,正在學習用心體會事物的本質跟不斷進入學生心態改進。
留言討論