Count the Number of Arrays with K Matching Adjacent Elements solution and explanation
9 more videos on this problem
Count the Number of Arrays with K Matching Adjacent Elements | Detailed Approach | Leetcode 3405codestorywithMIK · 33:16 · 8K views
3405. Count the Number of Arrays with K Matching Adjacent Elements | Math | PnC | nCr | Mod InverseAryan Mittal · 19:56 · 6K views
Count the Number of Arrays with K Matching Adjacent Elements | Leetcode 3405Techdose · 14:45 · 6K views
3405. Count the Number of Arrays with K Matching Adjacent Elements | Leetcode Daily - PythonLeetcode Daily · 6:34 · 1K views
3405. Count the Number of Arrays with K Matching Adjacent Elements - Day 17/30 Leetcode June ChallenProgramming Live with Larry · 20:52 · 1K views
3405. Count the Number of Arrays with K Matching Adjacent Elements - LeetCode [Hard] - 17 June 2025Intuit & Code · 24:32 · 1K views
Leetcode 3405 | Count The Number Of Arrays With K Matching Adjacent Elements | Leetcode POTDCoding Grower · 34:34 · 587 views
Leetcode 3405. Count the Number of Arrays with K Matching Adjacent ElementsElite Code · 37:40 · 523 views
Leetcode 3405. Count the Number of Arrays with K Matching Adjacent Elements | Combinatorics + PythonStatLearn Tech · 13:40 · 435 views
3405. Count the Number of Arrays with K Matching Adjacent Elements (Leetcode Hard)Programming Live with Larry · 26:31 · 385 views
The problem
You are given three integers n, m, k. A good array arr of size n is defined as follows:
- Each element in
arris in the inclusive range[1, m]. - Exactly
kindicesi(where1 <= i < n) satisfy the conditionarr[i - 1] == arr[i].
Return the number of good arrays that can be formed.
Since the answer may be very large, return it modulo 109 + 7.
Example 1:
Input: n = 3, m = 2, k = 1
Output: 4
Explanation:
- There are 4 good arrays. They are
[1, 1, 2],[1, 2, 2],[2, 1, 1]and[2, 2, 1]. - Hence, the answer is 4.
Example 2:
Input: n = 4, m = 2, k = 2
Output: 6
Explanation:
- The good arrays are
[1, 1, 1, 2],[1, 1, 2, 2],[1, 2, 2, 2],[2, 1, 1, 1],[2, 2, 1, 1]and[2, 2, 2, 1]. - Hence, the answer is 6.
Example 3:
Input: n = 5, m = 2, k = 0
Output: 2
Explanation:
- The good arrays are
[1, 2, 1, 2, 1]and[2, 1, 2, 1, 2]. Hence, the answer is 2.
Constraints:
1 <= n <= 1051 <= m <= 1050 <= k <= n - 1
Approach overview
Problem Overview: You need to count how many arrays of length n using values 1..m contain exactly k adjacent positions where a[i] == a[i+1]. The challenge is counting valid configurations without enumerating all m^n possibilities.
Approach 1: Dynamic Programming on Adjacent Matches (O(n * k) time, O(k) space)
A direct way is to build the array position by position while tracking how many matching adjacent pairs have been formed. Let dp[i][j] represent the number of ways to construct the first i elements with exactly j matching adjacent pairs. When adding element a[i], you have two choices: match the previous element (a[i] = a[i-1]) which increases the match count, or choose a different value (m-1 options) which does not. Transition through these two cases while ensuring the match count never exceeds k. This approach demonstrates the structure of the problem clearly but becomes less attractive when n is large.
Approach 2: Combinatorics + Fast Power (O(log n) time, O(1) space)
The optimal solution comes from observing that only the n-1 adjacent gaps determine whether a pair matches. Choose exactly k of these gaps where a[i] = a[i+1]. The number of ways to choose these positions is C(n-1, k). Once the matching gaps are fixed, the array effectively splits into n-k segments where the value must change between segments.
The first element has m choices. For every non-matching boundary (n-1-k of them), the next element must differ from the previous value, giving m-1 choices each time. The total number of valid arrays becomes:
C(n-1, k) * m * (m-1)^(n-1-k)
Because results are typically required modulo a large prime, compute the power using fast exponentiation. This reduces the exponentiation cost to O(log n). Combination values can be computed using factorials or an iterative formula depending on constraints.
This approach relies on counting configurations instead of constructing arrays. It converts the problem into pure combinatorics and modular arithmetic from math, which is why it scales easily even when n is very large.
Recommended for interviews: The combinatorics formula with fast exponentiation is the expected solution. Explaining the DP idea first shows you understand the state transitions, but recognizing the combinatorial structure and deriving C(n-1, k) * m * (m-1)^(n-1-k) demonstrates stronger problem-solving and mathematical insight.
Solution
For an array of length n, there are n - 1 pairs of adjacent elements. We need to select k of these n - 1 adjacent pairs such that the two elements in each of these k pairs are equal, and the remaining n - 1 - k adjacent pairs have different elements.
This is equivalent to splitting the array n - 1 - k times, resulting in n - k segments, where all elements in each segment are equal. The number of ways to split is C_{n - 1}^{n - 1 - k} = C_{n - 1}^{k}.
For the first segment, we can choose any element from [1, m]. For the remaining n - k - 1 segments, we just need to ensure that the element in each segment is different from the previous segment, so each of these segments has m - 1 choices. In total, there are m times (m - 1)^{n - k - 1} ways to choose.
Combining the two parts above, we get the answer:
$
C_{n - 1}^{k} times m times (m - 1)^{n - k - 1} bmod (10^9 + 7)
In the code implementation, we can precompute factorials and inverses, and use fast power to calculate combinations.
Ignoring the preprocessing time and space, the time complexity is O(log (n - k)), and the space complexity is O(1)$.
mx = 10**5 + 10
mod = 10**9 + 7
f = [1] + [0] * mx
g = [1] + [0] * mx
for i in range(1, mx):
f[i] = f[i - 1] * i % mod
g[i] = pow(f[i], mod - 2, mod)
def comb(m: int, n: int) -> int:
return f[m] * g[n] * g[m - n] % mod
class Solution:
def countGoodArrays(self, n: int, m: int, k: int) -> int:
return comb(n - 1, k) * m * pow(m - 1, n - k - 1, mod) % modclass Solution {
private static final int N = (int) 1e5 + 10;
private static final int MOD = (int) 1e9 + 7;
private static final long[] f = new long[N];
private static final long[] g = new long[N];
static {
f[0] = 1;
g[0] = 1;
for (int i = 1; i < N; ++i) {
f[i] = f[i - 1] * i % MOD;
g[i] = qpow(f[i], MOD - 2);
}
}
public static long qpow(long a, int k) {
long res = 1;
while (k != 0) {
if ((k & 1) == 1) {
res = res * a % MOD;
}
k >>= 1;
a = a * a % MOD;
}
return res;
}
public static long comb(int m, int n) {
return (int) f[m] * g[n] % MOD * g[m - n] % MOD;
}
public int countGoodArrays(int n, int m, int k) {
return (int) (comb(n - 1, k) * m % MOD * qpow(m - 1, n - k - 1) % MOD);
}
}const int MX = 1e5 + 10;
const int MOD = 1e9 + 7;
long long f[MX];
long long g[MX];
long long qpow(long a, int k) {
long res = 1;
while (k != 0) {
if ((k & 1) == 1) {
res = res * a % MOD;
}
k >>= 1;
a = a * a % MOD;
}
return res;
}
int init = []() {
f[0] = g[0] = 1;
for (int i = 1; i < MX; ++i) {
f[i] = f[i - 1] * i % MOD;
g[i] = qpow(f[i], MOD - 2);
}
return 0;
}();
long long comb(int m, int n) {
return f[m] * g[n] % MOD * g[m - n] % MOD;
}
class Solution {
public:
int countGoodArrays(int n, int m, int k) {
return comb(n - 1, k) * m % MOD * qpow(m - 1, n - k - 1) % MOD;
}
};const MX = 1e5 + 10;
const MOD = BigInt(1e9 + 7);
const f: bigint[] = Array(MX).fill(1n);
const g: bigint[] = Array(MX).fill(1n);
function qpow(a: bigint, k: number): bigint {
let res = 1n;
while (k !== 0) {
if ((k & 1) === 1) {
res = (res * a) % MOD;
}
a = (a * a) % MOD;
k >>= 1;
}
return res;
}
(function init() {
for (let i = 1; i < MX; ++i) {
f[i] = (f[i - 1] * BigInt(i)) % MOD;
g[i] = qpow(f[i], Number(MOD - 2n));
}
})();
function comb(m: number, n: number): bigint {
return (((f[m] * g[n]) % MOD) * g[m - n]) % MOD;
}
export function countGoodArrays(n: number, m: number, k: number): number {
const ans = (((comb(n - 1, k) * BigInt(m)) % MOD) * qpow(BigInt(m - 1), n - k - 1)) % MOD;
return Number(ans);
}const MX = 1e5 + 10
const MOD = 1e9 + 7
var f [MX]int64
var g [MX]int64
func qpow(a int64, k int) int64 {
res := int64(1)
for k != 0 {
if k&1 == 1 {
res = res * a % MOD
}
a = a * a % MOD
k >>= 1
}
return res
}
func init() {
f[0], g[0] = 1, 1
for i := 1; i < MX; i++ {
f[i] = f[i-1] * int64(i) % MOD
g[i] = qpow(f[i], MOD-2)
}
}
func comb(m, n int) int64 {
return f[m] * g[n] % MOD * g[m-n] % MOD
}
func countGoodArrays(n int, m int, k int) int {
ans := comb(n-1, k) * int64(m) % MOD * qpow(int64(m-1), n-k-1) % MOD
return int(ans)
}impl Solution {
pub fn count_good_arrays(n: i32, m: i32, k: i32) -> i32 {
const N: usize = 1e5 as usize + 10;
const MOD: i64 = 1_000_000_007;
use std::sync::OnceLock;
static F: OnceLock<Vec<i64>> = OnceLock::new();
static G: OnceLock<Vec<i64>> = OnceLock::new();
fn qpow(mut a: i64, mut k: i64, m: i64) -> i64 {
let mut res = 1;
while k != 0 {
if k & 1 == 1 {
res = res * a % m;
}
a = a * a % m;
k >>= 1;
}
res
}
fn init() -> (&'static Vec<i64>, &'static Vec<i64>) {
F.get_or_init(|| {
let mut f = vec![1i64; N];
for i in 1..N {
f[i] = f[i - 1] * i as i64 % MOD;
}
f
});
G.get_or_init(|| {
let f = F.get().unwrap();
let mut g = vec![1i64; N];
for i in 1..N {
g[i] = qpow(f[i], MOD - 2, MOD);
}
g
});
(F.get().unwrap(), G.get().unwrap())
}
fn comb(f: &[i64], g: &[i64], m: usize, n: usize) -> i64 {
f[m] * g[n] % MOD * g[m - n] % MOD
}
let (f, g) = init();
let n = n as usize;
let m = m as i64;
let k = k as usize;
let c = comb(f, g, n - 1, k);
let pow = qpow(m - 1, (n - 1 - k) as i64, MOD);
(c * m % MOD * pow % MOD) as i32
}
}Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Dynamic Programming on Adjacent Matches | O(n * k) | O(k) | Useful for understanding transitions and when constraints are small |
| Combinatorics + Fast Power | O(log n) | O(1) | Optimal solution for large n; converts the problem to counting choices of matching gaps |
Frequently asked questions
Is Count the Number of Arrays with K Matching Adjacent Elements easy or hard?
The problem is rated Hard because the key insight is combinatorial. A brute force or straightforward DP approach is easy to derive, but recognizing that the n-1 gaps determine the number of matches and converting the problem into C(n-1, k) * m * (m-1)^(n-1-k) requires deeper mathematical reasoning.
Count the Number of Arrays with K Matching Adjacent Elements Python/Java solution
Implement the formula C(n-1, k) * m * (m-1)^(n-1-k) under modulo arithmetic. Use fast exponentiation to compute powers efficiently and either precompute factorials for combinations or calculate combinations iteratively. The same logic works in Python, Java, C++, Go, TypeScript, and Rust.
How to solve Count the Number of Arrays with K Matching Adjacent Elements in O(log n)?
Treat each adjacent pair as a gap that either matches or differs. Choose k of the n-1 gaps to be equal using combinations. The array then has m choices for the first element and m-1 choices for each of the n-1-k non-matching gaps. Compute the result as C(n-1, k) * m * (m-1)^(n-1-k) with fast exponentiation.
What is the best approach for Count the Number of Arrays with K Matching Adjacent Elements?
The most efficient method uses combinatorics. Choose k matching adjacent positions among the n-1 gaps using C(n-1, k). The first element has m choices, and every non-matching boundary has m-1 choices, producing the formula C(n-1, k) * m * (m-1)^(n-1-k). Fast exponentiation computes the power term in O(log n) time.
Is Count the Number of Arrays with K Matching Adjacent Elements asked at Google/Amazon/Meta?
This type of combinatorics counting problem appears in interviews at companies like Google, Amazon, and Meta, especially for roles that emphasize mathematical reasoning or competitive programming style questions. Variants involving adjacent constraints and combinatorial counting are common.
What data structure is used in Count the Number of Arrays with K Matching Adjacent Elements?
The optimal solution does not rely on complex data structures. It primarily uses mathematical computation: combinations, modular arithmetic, and fast exponentiation. A dynamic programming version may use an array to store dp states for match counts.
What is the time complexity of Count the Number of Arrays with K Matching Adjacent Elements?
The optimal combinatorics solution runs in O(log n) time due to fast modular exponentiation. Space complexity is O(1) aside from constant arithmetic variables. A dynamic programming alternative takes O(n * k) time and O(k) space.
