這是來自 LIOJ 上的題目,因為我居然感到困惑,所以想記錄下來。
找出規律
這一題其實就難在找規律,規律如果找不出來,就會想不出解法。
先試著觀察看看:
1 | * |
要找出的規律是「每行有幾個星星」跟「每行有幾個空格」。
先看空格的部分:
- 第一行有 2 個空白
- 第二行有 1 個空白
- 第三行有 0 個空白
這裡假設 n
= 全部有幾行,i
= 目前的行數,換句話說就是最外層迴圈的次數:
1 | for(let i=1; i<=n; i++) { |
仔細觀察一下可以看出空白的數量跟 n
還有 i
有關,也就是 n-i
= 那一行需要的空格數:
- 第一行有
3-1
個空白 - 第二行有
3-2
個空白 - 第三行有
3-3
個空白
所以空格的部分可以這樣處理:
1 | for(let i=1; i<=n; i++) { |
接著來看星星的部分:
- 第一行有 1 個星星
- 第二行有 3 個星星
- 第三行有 5 個星星
這裡也是我卡住的地方,因為我沒辦法從 n
跟 i
之間找出這個規律,也不知道該從哪裡思考,
不過後來想想其實可以用「數學函數」的方式來思考,例如:
f(i) = 對 i 做某個算式 = 輸出值
f(1) = 1
f(2) = 3
f(3) = 5
從這裡可以發現規律是 「每一圈都會增加 2」,也就是說,每一圈都要 x2
:
1 | f(i) = i * 2 |
做到這裡後應該不難發現,只要再把每一項 -1
,就能達成目標:
1 | f(i) = i * 2 - 1 |
所以最後 2i-1
可以完成這個函數,規律就找出來了:
1 | for(let i=1; i<=n; i++) { |
最後把整個程式組合一下:
1 | for(let i=1; i<=n; i++) { |
這樣就解完這題了。
最後再考你一題:
1 | f(1) = 0 |
想完再來看解答
答案是:f(i) = 2i - 2紀錄
附上原始程式碼,原本的想法是「建立一個奇數陣列來做 mapping」:
- 第 1 行會在
createStarts()
代入 1,產出 1 個星星 - 第 2 行會在
createStarts()
代入 3,產出 3 個星星 - 第 3 行會在
createStarts()
代入 5,產出 5 個星星 - 以此類推
1 | function solve(lines) { |