Understand
30-second explanation
Build the interview-ready mental model before comparing implementations.
Count arrays of length n with values in [1, k], where a[0] = 1, a[n−1] = x, and consecutive elements differ. Track two counts: `same` = number of valid prefixes whose current element equals the target x, and `diff` = number whose current element is anything except x. The transitions are pure combinatorics: to land on x next you must come from a non-x element (diff ways), and to land on a non-x element you can come from an x-element via any of (k−1) choices or from a non-x element via (k−2) choices (excluding both x and the current value). Take everything mod 1e9+7. Answer = same after n steps. O(n) time, O(1) space.
Interview contextWhat is testedWhere candidates slipHow to stand outExplore interview contextHide interview context
What's being tested
Whether you bucket the k possible end-values into two equivalence classes (x vs not-x) and write a correct combinatorial recurrence, applying the modulus at every step.
Where candidates slip
Tracking k separate counts (O(n·k) and unnecessary), getting the (k−1) vs (k−2) multipliers backwards, or forgetting to mod the multiplications and overflowing.
How to stand out
Derive the two-class recurrence from first principles (why k−1 and why k−2), then mention the O(log n) closed form via modular inverse for huge n.
Choose
Compare the available approaches
Use constraints and trade-offs to select the route you can defend in an interview.
Interactive decision treeInteractiveChoose the right approachExplore the full treeCollapse the tree
How to read it:All non-x values collapse into one bucket; arrows carry the combinatorial multipliers.
Learn & trace
Build each solution step by step
Move from the core idea to a visual trace, implementation, proof, and edge cases.
Approach 1 of 3
Brute Force — Recurse over Every Next Value
1Hint 1Explore hintHide hint
Build the array position by position. At each step, try every value 1..k that differs from the previous element, and recurse.
2Hint 2Explore hintHide hint
Count an array only when you reach length n with the last value equal to x.
3Hint 3Explore hintHide hint
There are up to (k−1) choices per step → (k−1)ⁿ leaves. But the count of continuations depends only on (position, previous value) — heavily overlapping.
A · Core idea
The literal interpretation: grow the array one slot at a time, branching on every legal next value.
The recursion. Define f(i, prev) = the number of ways to complete the array from position i given that position i−1 holds value prev. At position i try every value v ≠ prev in [1, k] and sum f(i+1, v). The base case at i = n returns 1 if prev == x, else 0. Start with f(1, 1) since a[0] = 1 is fixed.
Why it counts correctly. Each root-to-leaf path is a distinct valid array (consecutive-different is enforced by v ≠ prev), and we tally only those ending at x. No array is counted twice because the choices at each position are disjoint.
Why it's hopeless at scale. Each position fans out to k−1 children, so the tree has (k−1)ⁿ leaves — for n = k = 10⁵ this is beyond astronomical. Yet f(i, prev) depends only on i and on whether `prev` equals `x` (all non-x previous values give the identical count). That means there are really only 2n distinct subproblems hiding behind exponentially many calls — the cue to bucket and memoize.
B · Visual dry run
Interactive dry run
Select a frame to connect the decision with its visual state.
n = 3, k = 3, x = 1Interactive diagram
Branching on every legal next value
pos 1 from prev=1States differing only by a non-x previous value are identical — the redundancy memoization removes.
2C · Code with teaching comments
Reference implementation previewpublic int countArray(int n, int k, int x) { return f(1, 1, n, k, x); } private int f(int i, int prev, int n, int k, int x) {Explore the full codeHide the full code
D · Why it works and complexityO(kⁿ) timeO(n) spaceOpen the invariant and proofExplore the proofHide the proof
The count of continuations from a position depends on the previous value only through 'is it x or not'. Recognising that all non-x values are interchangeable collapses k branches' worth of distinct states into just two — turning O(kⁿ) into O(n).
ComplexityO(kⁿ) time, O(n) space — Up to (k−1) branches at each of n positions gives O(kⁿ) leaves; recursion depth O(n).
E · Edge cases and pitfalls3Tracking the exact previous value as state — k× more states than needed.Explore edge casesHide edge cases
Pitfalls
- Tracking the exact previous value as state — k× more states than needed.
- Forgetting the modulus, overflowing the running sum.
- Running it for n, k = 10⁵ — (k−1)ⁿ never returns.
Approach 2 of 3 · Optimal
Two-Bucket Counting DP (Optimal)
1Hint 1Explore hintHide hint
Collapse the k end-values into two classes: `same` = arrays whose current last element is x, `diff` = arrays whose last element is anything but x.
2Hint 2Explore hintHide hint
To extend onto x: the previous element must not be x → new_same = diff. To extend onto a non-x value: from an x-element you have (k−1) non-x targets; from a non-x element you exclude both x and the current value → (k−2). So new_diff = same·(k−1) + diff·(k−2).
3Hint 3Explore hintHide hint
Base case from a[0]=1: same = (x==1), diff = (x!=1). Iterate to length n, mod everything, answer = same.
A · Core idea
Bucket the end-value into two equivalence classes and count each class in bulk.
States. After fixing the first i elements, let same be the number of valid arrays whose i-th element equals x, and diff the number whose i-th element is some value other than x. Every array of length i falls into exactly one bucket, so same + diff is the total count of valid length-i prefixes.
Transition to length i+1.
- Landing on x (
new_same): the next element isx, which must differ from the current one, so the current element cannot bex. Onlydiffarrays qualify, and there's exactly one value (x) to place →new_same = diff. - Landing on a non-x value (
new_diff):- From a
samearray (current element isx): any value exceptxis both legal (differs fromx) and non-x →k − 1choices. - From a
diffarray (current element is somey ≠ x): the next value must differ fromyand must not bex, so we exclude two values (yandx) →k − 2choices. - Total:
new_diff = same·(k−1) + diff·(k−2).
Base case. The array starts at a[0] = 1. So the length-1 array is [1]: it ends at x iff x == 1. Set same = (x == 1 ? 1 : 0), diff = (x == 1 ? 0 : 1).
Modular discipline. Counts blow up like (k−1)ⁿ. Apply % MOD after the addition and keep the multiplications in 64-bit (long) before reducing, since same·(k−1) with both near 10⁹ reaches ~10¹⁸ — fine for long, overflow for int. Add the two terms, then reduce.
Answer. After iterating up to length n, same holds the number of arrays ending at x — exactly what the problem asks.
B · Visual dry run
Interactive dry run
Select a frame to connect the decision with its visual state.
n = 4, k = 3, x = 2Array state
len 1
same=0, diff=1
3C · Code with teaching comments
D · Why it works and complexityO(n) timeO(1) spaceOpen the invariant and proofExplore the proofHide the proof
The k values aren't all distinct for counting — only the target x is special. Splitting into 'is x' / 'is not x' is the equivalence-class reduction that powers the whole solution; the (k−1) vs (k−2) multipliers fall straight out of 'how many legal next values does each class have'.
ComplexityO(n) time, O(1) space — One loop of n−1 steps, each doing O(1) modular arithmetic → O(n) time. Two rolling counters → O(1) space.
E · Edge cases and pitfalls7n = 1, x = 1 — Loop never runs; same=1 → answer 1 (the array [1]).Explore edge casesHide edge cases
Edge cases handled
n = 1, x = 1Loop never runs; same=1 → answer 1 (the array [1]).n = 1, x = 2same=0; answer 0 — a length-1 array can only end at 1.n = 3, k = 3, x = 1same toggles back: len2 same=0 diff=2... ends same=2 → [1,2,1],[1,3,1].k = 1k−2 = −1; only n=1,x=1 is valid → 1, all longer arrays impossible (no different neighbour).
Pitfalls
- Swapping (k−1) and (k−2) — the x-element class has one more legal target than the non-x class.
- Using int for the products — same·(k−1) overflows; use long and mod each factor.
- Mis-seeding the base case (e.g. same=1 regardless of x) — a[0]=1 dictates it.
Approach 3 of 3
Closed Form via Modular Inverse — O(log n)
1Hint 1Explore hintHide hint
The recurrence has a closed form. Walks of length n−1 on the complete graph Kₖ from a fixed start: the count splits by whether the end equals the start's value class.
2Hint 2Explore hintHide hint
If x ≠ 1: answer = ((k−1)^(n−1) − (−1)^(n−1)) / k. If x = 1: answer = ((k−1)^(n−1) + (k−1)·(−1)^(n−1)) / k.
3Hint 3Explore hintHide hint
Division mod a prime is multiplication by the modular inverse: divide by k using k^(MOD−2) (Fermat's little theorem).
A · Core idea
The two-bucket recurrence is linear, so it has a closed form — useful when n is enormous and even O(n) is too slow.
The formula. Building the array is equivalent to counting walks of length n−1 on the complete graph K_k (every value adjacent to every other value) starting at the vertex 1:
- Ending at a vertex different from the start (
x ≠ 1):((k−1)^(n−1) − (−1)^(n−1)) / k. - Ending back at the start (
x = 1):((k−1)^(n−1) + (k−1)·(−1)^(n−1)) / k.
Why a sign term. The number of closed vs open walks oscillates with parity; the (−1)^(n−1) correction captures that the simple (k−1)^(n−1) over-counts or under-counts depending on whether n−1 is even or odd.
Dividing under a modulus. You can't just divide by k in modular arithmetic — instead multiply by k's modular inverse. Since MOD = 1e9+7 is prime, Fermat's little theorem gives k⁻¹ ≡ k^(MOD−2) (mod MOD). Compute (k−1)^(n−1) mod MOD and k^(MOD−2) mod MOD with fast exponentiation, combine, and normalise any negative intermediate by adding MOD.
When to prefer it. The two-bucket DP is simpler and plenty fast for n ≤ 10⁵. Reach for the closed form only when n can be astronomically large (e.g. given as an exponent) and you need sub-linear time. The trade-off is the subtlety of the parity sign and the modular-inverse machinery.
B · Visual dry run
Interactive dry run
Select a frame to connect the decision with its visual state.
n = 4, k = 3, x = 2 (x ≠ 1)Interactive diagram
Closed form pipeline
powerExponentiate, sign-correct, then divide by k via modular inverse.
3C · Code with teaching comments
Reference implementation previewpublic int countArray(int n, int k, int x) { final long MOD = 1_000_000_007L; long base = power(k - 1, n - 1, MOD); long sign = ((n - 1) % 2 == 0) ? 1 : MOD - 1; // +1 or -1 mod p long numerator;Explore the full codeHide the full code
D · Why it works and complexityO(log n) timeO(1) spaceOpen the invariant and proofExplore the proofHide the proof
A linear two-state recurrence is a 2×2 matrix power, which always admits a closed form. Here the eigenstructure of K_k yields the clean (k−1)^(n−1) term plus a parity correction — and the modular inverse is just how you 'divide by k' inside a prime field.
ComplexityO(log n) time, O(1) space — Fast modular exponentiation for (k−1)^(n−1) and for the inverse of k each take O(log n) (or O(log MOD)) multiplications → O(log n) total.
E · Edge cases and pitfalls6n = 4, k = 3, x = 1 — ((2)³ + 2·(−1)) / 3 = (8−2)/3 = 2 — matches enumeration.Explore edge casesHide edge cases
Edge cases handled
n = 4, k = 3, x = 1((2)³ + 2·(−1)) / 3 = (8−2)/3 = 2 — matches enumeration.n = 100, k = 100, x = 1Closed form gives 758049401, identical to the O(n) DP.k = 1Modular inverse of 1 is 1; formula degenerates correctly for the trivial single-value case.
Pitfalls
- Forgetting to add MOD before reducing a subtraction — produces a negative result.
- Using floating-point division by k instead of the modular inverse — loses exactness.
- Getting the parity sign or the x==1 vs x≠1 branch wrong — the two cases differ.
Practice
Try the solution yourself
Edit the optimal implementation, test another input, and observe the result.
Editable code previewpublic int countArray(int n, int k, int x) { final long MOD = 1_000_000_007L; long same = (x == 1) ? 1 : 0; long diff = (x == 1) ? 0 : 1; for (int i = 2; i <= n; i++) {Explore the playgroundClose the playground
Avoid mistakes
Recognize the interview traps
Understand why common attempts fail before reviewing the corrected implementation.
1Tracking every value separately
All non-x values are interchangeable for counting. Keeping k counters is O(n·k) and needless; two buckets suffice.
Explore the code comparisonHide the code comparison
Tracking every value separately
All non-x values are interchangeable for counting. Keeping k counters is O(n·k) and needless; two buckets suffice.
Don't write this
dp = [[0] * (k + 1) for _ in range(n + 1)]
# fills k columns per row — O(n*k)Write this instead
same, diff = (x == 1), (x != 1)
for _ in range(2, n + 1):
same, diff = diff, (same * (k - 1) + diff * (k - 2)) % MOD2Wrong multipliers
From an x-element there are k−1 non-x targets; from a non-x element you also exclude the current value, leaving k−2. Swapping them miscounts.
Explore the code comparisonHide the code comparison
Wrong multipliers
From an x-element there are k−1 non-x targets; from a non-x element you also exclude the current value, leaving k−2. Swapping them miscounts.
Don't write this
newDiff = (same * (k - 2) + diff * (k - 1)) % MOD; // swappedWrite this instead
newDiff = (same * (k - 1) % MOD + diff * (k - 2) % MOD) % MOD;3Overflow on the products
same and (k−1) can each be near 10⁹; their product is ~10¹⁸, overflowing int and risking overflow if you add two such products before reducing.
Explore the code comparisonHide the code comparison
Overflow on the products
same and (k−1) can each be near 10⁹; their product is ~10¹⁸, overflowing int and risking overflow if you add two such products before reducing.
Don't write this
int newDiff = same * (k - 1) + diff * (k - 2); // int overflowWrite this instead
long newDiff = (same * (k - 1) % MOD + diff * (k - 2) % MOD) % MOD;Revise
Carry the pattern into the interview
Pattern to remember
Two-bucket counting DP (ends-at-x vs ends-elsewhere), modular
Code pattern to memorize
MOD = 1e9+7
same, diff = (1 if x==1 else 0), (0 if x==1 else 1) # length-1: a[0]=1
for i in 2..n:
new_same = diff # only a non-x can step onto x
new_diff = same*(k-1) + diff*(k-2) # step onto a non-x value
same, diff = new_same % MOD, new_diff % MOD
answer = sameRules to remember
- 1Bucket states by value class, not by value: 'equals x' vs 'not x'. All non-x values behave identically, so one count suffices for the whole bucket.
- 2
new_same = diff: you can only arrive at x from something that isn't x (consecutive must differ), and there's exactly one value x to land on. - 3
new_diff = same·(k−1) + diff·(k−2): from an x-element any of the other (k−1) values is non-x; from a non-x element you exclude both the current value and x → (k−2). - 4Reduce every arithmetic step mod 1e9+7, including the multiplications — products of two ~1e9 counts overflow 32-bit and even flirt with 64-bit if you batch them.
- 5Seed the base case from a[0] = 1: if x == 1 the length-1 array already ends at x (same=1), otherwise it ends elsewhere (diff=1).
Use this pattern when
- Count sequences/arrays under adjacency constraints (consecutive differ, no two equal, etc.)
- States collapse into a few equivalence classes you can count in bulk
- Answer required modulo a large prime → modular counting DP
- Walks on a complete-graph-like structure with fixed start and end
Choose another pattern when
- You must enumerate or output the arrays, not count them → backtracking, not DP
- Constraints couple non-adjacent positions arbitrarily → richer state needed
- Values aren't interchangeable (each has distinct rules) → can't bucket into 2 classes
- No modulus and n is tiny → a closed-form or direct formula may be simpler
Interview takeaway
When counting constrained sequences, group states into equivalence classes you can count together — here just 'ends at x' and 'ends elsewhere'. Two rolling counters and careful modular arithmetic turn an exponential enumeration into an O(n) recurrence.
Continue
Transfer the pattern to another problem
Use a direct variation or pattern sibling to prove the idea is reusable.
Transferable patternModular counting DP with equivalence-class state compression. When counting constrained sequences, bucket states into a few classes you can count in bulk (here ends-at-x vs ends-elsewhere). The linear recurrence also yields an O(log n) closed form via modular inverse. Same counting mindset as Climbing Stairs and Decode Ways.
Practice queueDirect variations and pattern siblings
Direct follow-ups
- Climbing StairsThe simplest two-term counting recurrence — same rolling-variable technique without the modulus subtlety.
- Decode WaysCounting valid sequences under adjacency-style constraints — a richer state but the same counting-DP mindset.
- The Coin Change Problem (Count Ways)Counting combinations with a modulus — practice with modular counting DP.
- Count Paths in GridCombinatorial path counting — another DP where states aggregate many concrete configurations.