We use cookies to ensure you have the best browsing experience on our website. Please read our cookie policy for more information about how we use cookies.
Construct the Array
Construct the Array
Sort by
recency
|
173 Discussions
|
Please Login in order to post a comment
Stage 1: Brute-Force Dynamic Programming (O(NK) Time, O(NK) Space)
Intuition: We want to find the number of valid arrays of length
n
ending withx
. A natural approach is to build up the solution from smaller arrays. We can definedp[i][j]
as the number of ways to form an array of lengthi
where the last element isj
. To form an array of lengthi
ending inj
, the previous element (at lengthi-1
) must be different fromj
. Thus,dp[i][j]
is the sum ofdp[i-1][p]
for allp
from1
tok
wherep != j
.Code:
Minor Optimizations Instead of looping to sum previous row, we can keep a separate sum variable, populate it directly when we were calculating the previous row.
Stage 2: Space Optimization (O(NK) Time, O(K) Space)
Intuition: Since the current row
dp[i]
only depends on the previous rowdp[i-1]
, we can optimize the space by only storing the counts for the previous length. We'll use two vectors,prev
andcurr
, whereprev
holds the counts for lengthL
andcurr
computes counts for lengthL+1
. After computingcurr
, it becomes the newprev
for the next iteration.Code:
Minor Optimization: Actually we don't even need 2 vector, since
curr[a]
only depends onprev[a]
. You can actually just have 1 vector, and update in place.Stage 3: Full Optimization (O(N) Time, O(1) Space)
Intuition: The core observation is that all numbers
j
from2
tok
behave identically in their recurrence relations, as long asj
is not1
. This allows us to collapsek-1
distinct states into a single "ends with non-1" category. We only need to track two values:dp_ends_with_1
: number of arrays of lengthL
ending with1
.dp_ends_with_other
: number of arrays of lengthL
ending with any value in[2, k]
Recurrence Relations:
next_dp_ends_with_1
(array ends with1
): The previous element must have beennot 1
. So,next_dp_ends_with_1 = dp_ends_with_other
.next_dp_ends_with_other
(array ends with somej != 1
):1
: There weredp_ends_with_1
ways to end with1
. We can then append any of the(k-1)
non-1 values. Contribution:dp_ends_with_1 * (k-1)
.p != 1
: There weredp_ends_with_other
ways to end with any non-1 value. We can then append any of the(k-2)
non-1 values that are different fromp
. Contribution:dp_ends_with_other * (k-2)
.Code:
My initial solution - which consumed too much memory - involved computing the number of arrays that could be constructed that concluded with a specific number l but, at its limit it creates a memoisation array of size 4 x 10¹⁰ bytes which is... a bit too much RAM usage. However, ultimately all that matters is whether or not it ended with x or not.
Cautious, the modulo requirement can make a Huge difference. You may not pass other tests than 0 & 1 unless "mod" is used in the correct place and with correct value, even if your solution is all correct.
This problem required very little memoization. I noticed a pattern; consider the number of arrays of length 2: [0,1,1] where index is the ending number x. Using a dynamic coding strategy, you might try to find the number of arrays of length 3 by summing up elements of this array: [2,1,1] You don't add the number of arrays of length 2 ending in the same x, since the numbers can't appear twice in a row. Therefore, index 1 is one greater, since it ignored the one element that was 1 less than the others. Using this array, the number of arrays of length 4 is: [2,3,3] This time, index 1 is one less since it ignored the one element that was one more than the rest. The pattern continues: [6,5,5] [10,11,11]
So we can ditch using arrays and just consider the number of arrays ending in x>1. The number N(n) of arrays of length n ending in x>1 is equal to (k-1)*N(n-1) + (1 if n is even, -1 if n is odd)
if x==1, subtract 1 if n is even, add 1 if n is odd
Did not understand why my code passed only first 2 testcases and failed all the rest until I realized that the modulo code was not in the right place.
If you comment your modulo code and it passes the testcases below when n<12 but will fail as soon as n=12 , then your code is very close to the solution.
10 10 2 38742049
11 10 2 348678440
12 10 2 138105940