來自 LIOJ 上的題目,也是蠻有趣的一題。
常犯的錯誤
如果看完題目直接開始做,通常我們會這樣子寫:
1 | function isSequence(arr) { |
為什麼最後是 false?
因為當迴圈跑到 i=4
的時候,裡面的 array[i+1]
會有問題 => array[5]
沒有元素。
所以這個時候迴圈的條件就得改成 for(let i=1; i<array.length-1; i++)
,雖然這樣就能得出正確結果,但同時也是很不直覺的寫法。
寫迴圈時都該注意最大與最小範圍
當 i 是從 1 ~ n-1
的時候,如果出現 i+1
,那就意味著會超出迴圈的「最大範圍」;或反過來說,如果 i 是從 0 ~ n-1
,那 i-1
就會超出迴圈的「最小範圍」。只要其中一項發生,那你的執行結果就一定會有問題。
更好的做法-預設值
我們可以先假設一個預設的「公比值」,接著在利用迴圈來做判斷:
1 | function isSequence(arr) { |
如果一個數列真的是「等比數列」,那一定會符合我們預設的公比,所以能做出正確的判斷。
另外,迴圈區塊中的 arr[i]
都有乖乖待在迴圈的最大與最小範圍,所以不會有超出的問題。
所以這樣子寫起來就相對直覺,也能解出正確的解答。這個做法就跟 求次大值 的概念雷同,都是先假設一個「預設值」來做判斷。
養成好習慣,適當處理邊角案例
這一題的邊角案例會是 []
或是 [1]
,就是「空陣列」或是「只有一個元素」。如果假設這兩個 case 都視為等比數列,那我們應該會這樣寫:
1 | function isSequence(arr) { |
但其實你仔細觀察會發現,就算不加上這個判斷,最後的結果也會是 true
。
1 | function isSequence(arr) { |
這是因為當 arr.length
為 0 或 1 的時候,不會通過迴圈的判斷條件 i < arr.length
,也就是說不會進到迴圈裡面,直接跳到 return true
的部分。
儘管以這個例子來說確實可以不加上額外判斷,可是還是會建議你加上去,這是一個比較好的習慣。因為如果換成其他的程式語言,在執行到 arr[1]
或 arr[0]
卻發現存取不到元素的時候,是有機會直接噴出一個 error,然後你的程式就執行不下去,最後就 GG 了。