Push DP vs Pull DP
Target Audience : If you are not able to come up with the
For an
is true if the prefix can be sent over a network.
How do we perform the transitions? For a fixed
for (int i = 0; i < n; i++) {
// The last segment is [j, i] (inclusive of length).
for (int j = i - 1; j >= 0; j--) {
int len = i - j;
if ((a[i] == len) || (a[j] == len)) {
dp[i] = dp[i] || (j ? dp[j - 1] : true);
}
}
}
The time complexity of this solution is
Notice that there can be 2 types of valid segments, one where the length is written to the right and one where the length is written to the left.
Let’s consider the first type of segment, with length to the right. Since the length is fixed to
Then, let’s consider the second type of segment, where the length is present to the left. However, in this case, we are not sure where the segment starts, so we end up scanning everything towards the left. Also, there can be multiple possible candidates for
In the current DP, we are pulling contributions from various indices. This is known as Pull DP.

So far we’ve been focusing on
So, instead of going backwards and pulling contribution from each
for (int i = 0; i < n; i++) {
// Suppose last segment is [j,i].
// Then, i - j = a[i] ==> j = i - a[i]
// Therefore, we need to pull contribution from j - 1.
int j = i - a[i];
if (j == 0) {
dp[i] = true;
} else if (j > 0) {
dp[i] = dp[i] || dp[j - 1];
}
// Push the contribution forward.
// Suppose last segment is [i,j].
// Then, j - i = a[i] ==> j = i + a[i].
// Therefore, we need to push contribution to j.
j = i + a[i];
if (j < n) {
if (i == 0) {
dp[j] = true;
} else if (i > 0) {
dp[j] = dp[j] || dp[i - 1];
}
}
}
The above code is a combination of Pull DP (for rightmost length) and Push DP (for leftmost length). Since there’s just a single loop, the time complexity is
Note : For push DP, always make sure to avoid partial updates, i.e, if