Skip to content
dsa450for five year olds

Dynamic Programming · 12 of 60

Painting the Fence problem

Count the ways to paint a row of fence posts with k colors so that no three posts in a row share a color.

Simple way
time O(2^n)
room O(n)
Clever way
time O(n)
room O(1)

The problem, simply

A fence has n posts in a row and you have k paint colors. Paint every post. The one rule: you may not have three or more posts next to each other in the same color. Two in a row is fine.

Give back how many different ways there are to paint the fence. The answer gets huge, so most versions ask for it modulo 1,000,000,007.

A story to remember it

Picture it

treeall paintings of 3 posts with red (R) and blue (B)
goRRRBBRBBRRBBRBnono

Every way to paint 3 posts with 2 colors. Red red red and blue blue blue break the rule, which leaves 6 good paintings.

  • answer
  • rejected

Examples

Three posts, two colors

In
n = 3, k = 2
Out
6

8 colorings in all, minus RRR and BBB.

Two posts

In
n = 2, k = 4
Out
16

Any two colors are fine, even the same twice: 4 x 4.

Five posts, three colors

In
n = 5, k = 3
Out
180

The walkthrough below builds this number post by post.

One color only

In
n = 4, k = 1
Out
0

With one color, posts 1, 2 and 3 would all match. No good painting exists. With n = 2, k = 1 the answer is 1.

One post

In
n = 1, k = 5
Out
5

Any color works.

Way 1: the simple way

Look at the last post. Call T(i) the number of good paintings of i posts.

  • If the last post has a new color, the first i - 1 posts can be any good painting, and you have k - 1 new colors. That gives (k - 1) x T(i - 1).
  • If the last post copies the one before, then those two form a pair, and that pair must be a switch from post i - 2. That gives (k - 1) x T(i - 2).

So T(i) = (k - 1) x (T(i - 1) + T(i - 2)), with T(1) = k and T(2) = k x k. Write it as a plain recursive function.

treeT(i) = ways to paint i posts
T5T4T3T2T1T2T3T2T1againagainagainagain

The calls for T(5). T(3) is worked out twice and T(2) three times. The bigger n gets, the more repeats there are, just like Fibonacci.

  • checking
java
class Solution {
    static final long MOD = 1_000_000_007L;

    public long countWays(int n, int k) {
        if (n == 0) return 0;
        if (n == 1) return k % MOD;
        if (n == 2) return (long) k * k % MOD;
        // new color after any painting of n-1, or a pair after any painting of n-2
        return (k - 1) * ((countWays(n - 1, k) + countWays(n - 2, k)) % MOD) % MOD;
    }
}

How long it takes: each call makes two calls, so the work grows like Fibonacci numbers, about O(2^n). Extra room: the call chain, O(n).

Way 2: the clever way

Walk the posts from left to right and keep two counts.

  1. same: paintings whose last two posts match.
  2. diff: paintings whose last post has a new color.
  3. For the next post: newSame = diff (copying is only safe after a switch) and newDiff = (same + diff) x (k - 1) (switch after anything).
  4. The total for the current post is same + diff.

Five posts and three colors, one post at a time

01 / 09

gridways to paint posts 1..i
post 1post 2post 3post 4post 5samedifftotal033

Post 1 can take any of the 3 colors. There is no post before it, so we count it as a change: diff = 3, same = 0, total = 3.

k
3
  • looking now
  • checking
  • done
  • answer
  • just added
java
class Solution {
    static final long MOD = 1_000_000_007L;

    public long countWays(int n, int k) {
        if (n == 0) return 0;
        long same = 0;          // last two posts match
        long diff = k;          // post 1: any color counts as a switch
        for (int i = 2; i <= n; i++) {
            long newSame = diff;                          // copy only after a switch
            long newDiff = (same + diff) % MOD * (k - 1) % MOD; // switch after anything
            same = newSame;
            diff = newDiff;
        }
        return (same + diff) % MOD;
    }
}

How long it takes: one short step per post, O(n). Extra room: two numbers, O(1).

Watch out for

  • k = 1 should give 1 for one or two posts and 0 for three or more. The formulas handle it because k - 1 = 0.
  • Take the modulo after every multiply. (same + diff) x (k - 1) can overflow a long without it.
  • Read the rule carefully. Some versions (LeetCode 276) say "no more than two adjacent posts", which is this problem. A stricter version says no two adjacent posts may match at all, and then the answer is k x (k - 1)^(n - 1).

What interviewers ask next

  • What if no three in a row means "at most m in a row"? Keep m counts: paintings ending with a run of length 1, 2, ..., m. Each new post either extends the run or starts a new one with k - 1 colors.
  • Can you do it in O(log n)? Yes. The step from (same, diff) to the next pair is a fixed 2 by 2 multiply, so you can raise that 2 by 2 table to a power with repeated squaring.
  • Paint houses where each color has a price and no two neighbors match. That is the "paint house" problem: keep the cheapest cost ending in each color.

Remember this

Grown-up words: the two counts are DP states, T(i) = (k - 1)(T(i-1) + T(i-2)) is a recurrence relation, keeping only the last values is space optimization, and the repeated squaring trick is matrix exponentiation.