[LeetCode] #276 Paint Fence 解題

題目連結

題型解說

這是一題難度為簡單的題目

需要設計一個方法,此方法會傳入 柱子的數量(n) 及 顏色的數量(k)

且 n 與 k 為正整數

試問可以組合出幾種顏色的組合,且相同顏色不可以連續兩隻以上

範例: n = 3,k = 2 可以組合出六種結果

顏色我們就用 R 跟 B 代替

  • 第一種組合    R    R    B
  • 第二種組合    R    B    R
  • 第三種組合    R    B    B
  • 第四種組合    B    B    R
  • 第五種組合    B    R    B
  • 第六種組合    B    R    R

我們來看一下錯誤的組合

R   R   R

因為限制為相同顏色只能連續兩隻,所以一但三隻都漆上紅色,就違反規則

解題思路

這一題雖然列為簡單,但實際上還是有一定的難度

主要是想辦法發現規律,沒接觸過的人大概得要想半天吧

那我們就從柱子的數量來說一下規律,假設顏色有三種 R   G   B   

柱子數量為 1

如果柱子數量為 1,那答案就是顏色的數量 k,應該沒有什麼歧義

  • 第一種組合    R
  • 第二種組合    G
  • 第三種組合    B

柱子數量為 2

如果柱子數量為 2,第 2 隻柱子會有兩種選擇

  1. 與前一隻顏色一樣
  2. 與前一隻顏色不一樣

先來看第一種(與前一隻顏色一樣),比較單純,組合一樣是 k(3) 種

  • 第一種組合    R   R
  • 第二種組合    G   G
  • 第三種組合    B   B

再來看第二種(與前一隻顏色不一樣),組合是 (k(3) - 1) * 上一隻柱子的數量(3) = 6種

  • 第一種組合    R    G
  • 第二種組合    R    B
  • 第三種組合    G    R
  • 第四種組合    G    B
  • 第五種組合    B    R
  • 第六種組合    B    G

柱子數量為 2 的答案就是兩種選擇的數量的加總 6 + 3 = 9

柱子數量為 3

如果柱子數量為 3,第 3 隻柱子一樣會有兩種選擇

  1. 與前一隻顏色一樣
  2. 與前一隻顏色不一樣

一樣先看第一種(與前一隻顏色一樣),這邊要結合第二隻柱子的狀況來看,只有第二隻的第二種選擇的數量才是正確的,也就是 6 種

  • 第一種組合    R    G    G
  • 第二種組合    R    B    B
  • 第三種組合    G    R    R
  • 第四種組合    G    B    B
  • 第五種組合    B    R    R
  • 第六種組合    B    G    G

那為什麼不算第二隻的第一種選擇的數量呢?因為第二隻的第一種選擇已經與第一隻柱子的顏色相同了,如果第三隻還算進去的話就會變成違反規則

  • 第一種組合    R   R   R
  • 第二種組合    G   G   G
  • 第三種組合    B   B   B

上面哪一種組合都是違反規則的

再來看第二種(與前一隻顏色不一樣),組合是 (k(3) - 1) * 上一隻柱子的數量(9) = 18種

  • 第一種組合        R    R    G
  • 第二種組合        R    R    B
  • 第三種組合        G    G    R
  • 第四種組合        G    G    B
  • 第五種組合        B    B    R
  • 第六種組合        B    B    G
  • 第七種組合        R    G    R
  • 第八種組合        R    G    B
  • 第九種組合        R    B    R
  • 第十種組合        R    B    G
  • 第十一種組合    G    R    B
  • 第十二種組合    G    R    G
  • 第十三種組合    G    B    R
  • 第十四種組合    G    B    G
  • 第十五種組合    B    R    G
  • 第十六種組合    B    R    B
  • 第十七種組合    B    G    R
  • 第十八種組合    B    G    B

柱子數量為 3 的答案就是兩種選擇的數量的加總 6 + 18 = 24

柱子數量為 4 的情況就自己列列看吧,如果算出來的數量是 66 的話就對了

規律

由上面的範例來看,可以發現一個規律

第 n 隻柱子的組合數量為: 第 n - 1 隻柱子的第二種選擇(與前一隻顏色不一樣)的數量 + (k - 1) * 第 n - 1 隻柱子的總數

那第 n - 1 隻柱子的組合數量為: 第 n - 2 隻柱子的第二種選擇(與前一隻顏色不一樣)的數量 + (k - 1) * 第 n - 2 隻柱子的總數

以此類推,這樣就可以用一個迴圈來算出解答了

程式碼

Java

class Solution {
    public int numWays(int n, int k) {
        if (n == 0 || k == 0 || (k == 1 && n > 2)) {
            return 0;
        }
        
        if (n == 1) {
            return k;
        }
        
        int same = 0;  // 與上一隻柱子顏色相同
        int diff = k;  // 與上一隻柱子顏色不同
        int total = k; // 總數
        
        for (int i = 2; i <= n; i++) {
            same = diff;
            diff = (k -1) * total;
            total = same + diff;
        }
        
        return total;
    }
}

Read more

[LeetCode] #12 Integer to Roman 解題

題目連結 題型解說 這是一題難度為普通的題目 需要設計一個方法,此方法會傳入一個整數 num 要求是把整數轉換成羅馬字母,轉換清單如下 I => 1 V => 5 X => 10 L => 50 C => 100 D => 500 M => 1000 但羅馬字母有一些特殊規則 4 並非 IIII 而是 IV,9 並非 VIIII 而是 IX 這規則同樣可以套用到 40 90 400 900 解題思路 既然知道特殊規則是一樣的,變得是使用的符號,那麼先從 num 取個位數開始 轉換完成後,把 num 除上 10,消除個位數,

By Michael

[LeetCode] #11 Container With Most Water 解題

題目連結 題型解說 這是一題難度為中等的題目 需要設計一個方法,此方法會傳入一個數字陣列 height 陣列中的元素代表每一個柱子的高度 現在需要計算出,該陣列中以某兩隻柱子為邊界,最多可以裝多少水 以範例來說 height = [1,8,6,2,5,4,8,3,7] 最多可以裝 7 * 7 = 49 單位的水 解題思路 計算面積就是底乘上高 底的計算方式為 「右邊柱子的 index」 減去 「左邊柱子的 index」 高就取最短的那一根柱子高度 拿題目給的例子來當範例 建立三個變數 result、left、right left、right 代表左右兩邊的 index result 代表目前最大容量,初始值 0 第一步,找出最短的柱子高度,

By Michael

[LeetCode] #941 Valid Mountain Array 解題

題目連結 題型解說 這是一題難度為簡單的題目 需要設計一個方法,此方法會傳入一個數字陣列 arr 判斷陣列中的元素是不是由低到高再從高到低(山形)的排序,且不連續一個以上數字 比如說 [1,2,3,2] 就是一個山形陣列,但 [1,2,2,3,2] 不是,因為有兩個 2 [1,2,3,4,5] 和 [5,4,3,2,1] 也不算是山形陣列,前者只有往上沒有往下,後者相反 解題思路 準備一個數字變數(temp)和布林變數(asc),跑一次迴圈,有可能遇到如下狀況 1. 某個數字與前一個數字相同,這時候直接回傳 false

By Michael

[LeetCode] #944 Delete Columns to Make Sorted 解題

題目連結 題型解說 這是一題難度為簡單的題目 需要設計一個方法,此方法會傳入一個字串陣列 strs 這個陣列中每個字串的長度都相同,字串內容都是小寫英文 需要檢查每個元素的第 N 個字元是不是由小至大排列,並回傳有幾個錯誤排列 比如傳入的陣列長這樣 ["cba","daf","ghi"] 取第一個字元 = cdg 取第二個字元 = bah 取第三個字元 = afi 其中第二組的結果(bah)並不是由小至大排列,故回傳 1 解題思路 這一題就用兩個迴圈各別把字元取出來,並比較是否比上一個字元大(Java 中的字元可以直接比較),如果不是就將結果+1 程式碼 Java class Solution { public int minDeletionSize(String[] strs) { int result = 0; for (int i = 0,

By Michael