LeetCode 3339 - Find the Number of K-Even Arrays
We are given three integers: - n, the length of the array. - m, the maximum value allowed in the array. - k, the exact number of special adjacent positions we want. Every element of the array must be chosen from the range [1, m].
Difficulty: 🟡 Medium
Topics: Dynamic Programming
Solution
LeetCode 3339 - Find the Number of K-Even Arrays
Problem Understanding
We are given three integers:
n, the length of the array.m, the maximum value allowed in the array.k, the exact number of special adjacent positions we want.
Every element of the array must be chosen from the range [1, m].
For every adjacent pair (arr[i], arr[i + 1]), we evaluate:
$$(arr[i] \times arr[i+1]) - arr[i] - arr[i+1]$$
If this value is even, then index i contributes toward the count.
An array is called k-even if exactly k adjacent indices satisfy this property.
Our task is to count how many arrays of length n are k-even, and return the result modulo:
$$10^9 + 7$$
Key Observation About Parity
Only the parity of the numbers matters.
Let:
a = arr[i] mod 2b = arr[i+1] mod 2
Modulo 2,
$$ab - a - b \equiv ab + a + b$$
Checking all parity combinations:
| a | b | ab + a + b (mod 2) |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
The expression is even only when both numbers are even.
Therefore, the problem becomes:
Count arrays of length
nwhere exactlykadjacent pairs consist of two even numbers.
What the Constraints Tell Us
n ≤ 750k ≤ n - 1 ≤ 749m ≤ 1000
A brute force enumeration would require examining m^n arrays, which is completely infeasible.
The constraints strongly suggest a dynamic programming solution with complexity around O(nk).
Important Edge Cases
When m = 1, only the value 1 is available, which is odd. No adjacent pair can ever be an even-even pair.
When k = 0, we count arrays that avoid every even-even adjacency.
When k = n - 1, every adjacent pair must be even-even, which forces every element in the array to be even.
When there are no even numbers in [1, m], every valid array automatically has zero even-even pairs.
Approaches
Brute Force
A straightforward approach is to generate every possible array of length n.
For each array, we would inspect all n - 1 adjacent pairs and count how many satisfy the condition.
If the count equals k, we include the array in the answer.
This approach is correct because it explicitly checks every possible array. However, it is far too slow.
There are m^n possible arrays, which becomes astronomically large even for small inputs.
Optimal Dynamic Programming
The crucial observation is that only parity matters.
Let:
E = number of even values in [1, m]O = number of odd values in [1, m]
We do not care which even number was chosen, only whether the chosen number is even or odd.
While building the array from left to right, we need to know:
- how many even-even pairs have been created so far,
- whether the last element is even or odd.
This naturally leads to a dynamic programming state.
For every new element:
- Odd after odd creates no new even-even pair.
- Odd after even creates no new even-even pair.
- Even after odd creates no new even-even pair.
- Even after even creates exactly one new even-even pair.
This gives an O(nk) solution.
Approach Comparison
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(m^n · n) | O(n) | Enumerates every array |
| Optimal DP | O(nk) | O(k) | Tracks parity and number of even-even pairs |
Algorithm Walkthrough
Step 1: Count Even and Odd Values
Let:
evenCount = m // 2
oddCount = m - evenCount
These are the numbers of available even and odd values.
Step 2: Define DP States
Maintain two arrays:
dpEven[j]= number of arrays built so far that end with an even number and contain exactlyjeven-even pairs.dpOdd[j]= number of arrays built so far that end with an odd number and contain exactlyjeven-even pairs.
Step 3: Initialize Length 1
For arrays of length 1:
- Any even value creates an array ending in even.
- Any odd value creates an array ending in odd.
Therefore:
dpEven[0] = evenCount
dpOdd[0] = oddCount
Step 4: Extend the Array
For every new position:
- Even → Even
Creates one new even-even pair. 2. Even → Odd
Creates no new even-even pair. 3. Odd → Even
Creates no new even-even pair. 4. Odd → Odd
Creates no new even-even pair.
The transition formulas are:
newEven[j] += dpOdd[j] * evenCount
newEven[j+1] += dpEven[j] * evenCount
newOdd[j] += dpOdd[j] * oddCount
newOdd[j] += dpEven[j] * oddCount
All operations are performed modulo 1e9+7.
Step 5: Repeat Until Length n
Perform the transition n - 1 times.
Step 6: Return the Answer
The final answer is:
dpEven[k] + dpOdd[k]
modulo 1e9+7.
Why it Works
The DP maintains a complete description of every partial array using two pieces of information:
- the number of even-even pairs already formed,
- the parity of the last element.
Any future contribution depends only on the parity of the last element and the parity of the newly added element. Therefore no additional information is needed.
Since every valid extension is counted exactly once, and every possible array corresponds to exactly one sequence of transitions, the DP counts all k-even arrays correctly.
Python Solution
class Solution:
def countOfArrays(self, n: int, m: int, k: int) -> int:
MOD = 1_000_000_007
even_count = m // 2
odd_count = m - even_count
dp_even = [0] * (k + 1)
dp_odd = [0] * (k + 1)
dp_even[0] = even_count
dp_odd[0] = odd_count
for _ in range(1, n):
next_even = [0] * (k + 1)
next_odd = [0] * (k + 1)
for pairs in range(k + 1):
even_ways = dp_even[pairs]
odd_ways = dp_odd[pairs]
if even_ways:
next_odd[pairs] = (
next_odd[pairs]
+ even_ways * odd_count
) % MOD
if pairs < k:
next_even[pairs + 1] = (
next_even[pairs + 1]
+ even_ways * even_count
) % MOD
if odd_ways:
next_even[pairs] = (
next_even[pairs]
+ odd_ways * even_count
) % MOD
next_odd[pairs] = (
next_odd[pairs]
+ odd_ways * odd_count
) % MOD
dp_even = next_even
dp_odd = next_odd
return (dp_even[k] + dp_odd[k]) % MOD
Implementation Explanation
The code first computes how many even and odd values are available in the range [1, m].
Two DP arrays are maintained. One tracks arrays ending with an even value, while the other tracks arrays ending with an odd value.
For every new position, fresh arrays next_even and next_odd are constructed. The four possible parity transitions are applied. The only transition that increases the number of even-even pairs is the even-to-even transition.
After processing all positions, the answer is obtained by summing the states ending in either parity with exactly k even-even pairs.
Go Solution
func countOfArrays(n int, m int, k int) int {
const MOD int64 = 1_000_000_007
evenCount := m / 2
oddCount := m - evenCount
dpEven := make([]int64, k+1)
dpOdd := make([]int64, k+1)
dpEven[0] = int64(evenCount)
dpOdd[0] = int64(oddCount)
for pos := 1; pos < n; pos++ {
nextEven := make([]int64, k+1)
nextOdd := make([]int64, k+1)
for pairs := 0; pairs <= k; pairs++ {
evenWays := dpEven[pairs]
oddWays := dpOdd[pairs]
if evenWays != 0 {
nextOdd[pairs] = (nextOdd[pairs] +
evenWays*int64(oddCount)) % MOD
if pairs < k {
nextEven[pairs+1] = (nextEven[pairs+1] +
evenWays*int64(evenCount)) % MOD
}
}
if oddWays != 0 {
nextEven[pairs] = (nextEven[pairs] +
oddWays*int64(evenCount)) % MOD
nextOdd[pairs] = (nextOdd[pairs] +
oddWays*int64(oddCount)) % MOD
}
}
dpEven = nextEven
dpOdd = nextOdd
}
return int((dpEven[k] + dpOdd[k]) % MOD)
}
Go Specific Notes
The Go implementation uses int64 for all DP values because intermediate multiplication can exceed the range of a 32-bit integer.
Slices are used for the rolling DP arrays. At each iteration, new slices are allocated and then replace the old ones, exactly mirroring the rolling-array approach used in Python.
Worked Examples
Example 1
Input:
n = 3
m = 4
k = 2
Available values:
Even: {2, 4} => E = 2
Odd: {1, 3} => O = 2
Initial state:
| EE Pairs | End Even | End Odd |
|---|---|---|
| 0 | 2 | 2 |
After length 2:
| EE Pairs | End Even | End Odd |
|---|---|---|
| 0 | 4 | 8 |
| 1 | 4 | 0 |
After length 3:
| EE Pairs | End Even | End Odd |
|---|---|---|
| 0 | 16 | 24 |
| 1 | 16 | 8 |
| 2 | 8 | 0 |
Answer:
dpEven[2] + dpOdd[2]
= 8 + 0
= 8
Example 2
Input:
n = 5
m = 1
k = 0
We have:
E = 0
O = 1
Every element must be 1.
The only array is:
[1,1,1,1,1]
No even-even pair exists.
Answer:
1
Example 3
Input:
n = 7
m = 7
k = 5
We have:
E = 3
O = 4
Running the DP yields:
5832
which matches the expected output.
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(nk) | For each of n-1 positions we process all pair counts 0..k |
| Space | O(k) | Only two rolling DP arrays are stored |
The algorithm never depends directly on m beyond counting how many even and odd numbers exist. Therefore the running time is determined solely by n and k. With n ≤ 750 and k ≤ 749, this is easily fast enough.
Test Cases
sol = Solution()
assert sol.countOfArrays(3, 4, 2) == 8 # example 1
assert sol.countOfArrays(5, 1, 0) == 1 # example 2
assert sol.countOfArrays(7, 7, 5) == 5832 # example 3
assert sol.countOfArrays(1, 1, 0) == 1 # single element
assert sol.countOfArrays(1, 10, 0) == 10 # any single value works
assert sol.countOfArrays(2, 2, 1) == 1 # only [2,2]
assert sol.countOfArrays(2, 2, 0) == 3 # all others
assert sol.countOfArrays(3, 2, 2) == 1 # [2,2,2]
assert sol.countOfArrays(3, 1, 1) == 0 # no even numbers
assert sol.countOfArrays(4, 3, 3) == 0 # impossible to get 3 EE pairs
# with only one even value available
assert sol.countOfArrays(2, 1000, 0) > 0 # large m
assert sol.countOfArrays(750, 1, 0) == 1 # maximum n, only odd value
Test Summary
| Test | Why |
|---|---|
(3,4,2) |
Official example |
(5,1,0) |
Official example |
(7,7,5) |
Official example |
(1,1,0) |
Smallest input |
(1,10,0) |
Length one, no adjacency |
(2,2,1) |
Exactly one EE pair |
(2,2,0) |
Complement of previous case |
(3,2,2) |
Maximum possible EE count |
(3,1,1) |
No even numbers available |
(4,3,3) |
Impossible configuration |
(2,1000,0) |
Large value range |
(750,1,0) |
Maximum length edge case |
Edge Cases
Length One Arrays
When n = 1, there are no adjacent pairs at all. Therefore every valid array automatically has zero even-even pairs. A common bug is to assume at least one transition exists. The DP initialization handles this correctly because the answer is read directly from the length-one states.
No Even Numbers Available
When m = 1, the only value is 1, which is odd. In this situation, an even-even pair can never occur. The transitions involving even values contribute zero because evenCount = 0. The DP naturally collapses to counting only odd-ending arrays.
Maximum Possible Pair Count
The largest possible number of even-even pairs is n - 1, achieved only when every element is even. A common mistake is to allow transitions beyond k. The implementation explicitly checks pairs < k before creating a new even-even pair, preventing out-of-range states and ensuring correctness.
Impossible Configurations
Some (n, m, k) combinations cannot produce the requested number of even-even pairs. For example, if there are no even numbers available but k > 0, the answer must be zero. The DP automatically returns zero because no state with positive pair count can ever be reached.