immutable structure with implicitly defined <code>.equals()</code>, <code>.hashCode()</code>,
<code>.toString()</code> and getters for the attributes.</p></div></div>
<p>Because of the choice of <code>TreeMap</code>, we had to additionally define the ordering
on it.</p>
<p>In the <code>longestSlideDown</code> you can notice that the computation which used to be
at the end of the naïve version above, is now wrapped in an <code>if</code> statement that
checks for the presence of the position in the cache and computes the slide down
just when it's needed.</p>
<h2class="anchor anchorWithStickyNavbar_LWe7"id="time-complexity">Time complexity<ahref="#time-complexity"class="hash-link"aria-label="Direct link to Time complexity"title="Direct link to Time complexity"></a></h2>
<p>If you think that evaluating time complexity for this approach is a bit more
tricky, you are right. Keeping the cache in mind, it is not the easiest thing
to do. However there are some observations that might help us figure this out:</p>
<ol>
<li>Slide down from each position is calculated only once.</li>
<li>Once calculated, we use the result from the cache.</li>
</ol>
<p>Knowing this, we still cannot, at least easily, describe the time complexity of
finding the best slide down from a specific position, <strong>but</strong> we can bound it
from above for the <strong>whole</strong> run from the top. Now the question is how we can do
that!</p>
<p>Overall we are doing the same things for almost<sup><ahref="#user-content-fn-1"id="user-content-fnref-1"data-footnote-ref="true"aria-describedby="footnote-label">1</a></sup> all of the positions within
the pyramid:</p>
<ol>
<li>
<p>We calculate and store it (using the partial results stored in cache). This
is done only once.</p>
<p>For each calculation we take 2 values from the cache and insert one value.
Because we have chosen <code>TreeMap</code>, these 3 operations have logarithmic time
complexity and therefore this step is equivalent to <spanclass="katex"><spanclass="katex-mathml"><mathxmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>3</mn><mo>⋅</mo><msub><mrow><mi>log</mi><mo></mo></mrow><mn>2</mn></msub><mi>n</mi></mrow><annotationencoding="application/x-tex">3 \cdot \log_2{n}</annotation></semantics></math></span><spanclass="katex-html"aria-hidden="true"><spanclass="base"><spanclass="strut"style="height:0.6444em"></span><spanclass="mord">3</span><spanclass="mspace"style="margin-right:0.2222em"></span><spanclass="mbin">⋅</span><spanclass="mspace"style="margin-right:0.2222em"></span></span><spanclass="base"><spanclass="strut"style="height:0.9386em;vertical-align:-0.2441em"></span><spanclass="mop"><spanclass="mop">lo<spanstyle="margin-right:0.01389em">g</span></span><spanclass="msupsub"><spanclass="vlist-t vlist-t2"><spanclass="vlist-r"><spanclass="vlist"style="height:0.207em"><spanstyle="top:-2.4559em;margin-right:0.05em"><spanclass="pstrut"style="height:2.7em"></span><spanclass="sizing reset-size6 size3 mtight"><spanclass="mord mtight">2</span></span></span></span><spanclass="vlist-s"></span></span><spanclass="vlist-r"><spanclass="vlist"style="height:0.2441em"><span></span></span></span></span></span></span><spanclass="mspace"style="margin-right:0.1667em"></span><spanclass="mord"><spanclass="mord mathnormal">n</span></span></span></span></span>.</p>
<p>However for the sake of simplicity, we are going to account only for the
insertion, the reason is rather simple, if we include the 2 retrievals here,
it will be interleaved with the next step, therefore it is easier to keep the
retrievals in the following point.</p>
<divclass="theme-admonition theme-admonition-caution admonition_xJq3 alert alert--warning"><divclass="admonitionHeading_Gvgb"><spanclass="admonitionIcon_Rf37"><svgviewBox="0 0 16 16"><pathfill-rule="evenodd"d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>caution</div><divclass="admonitionContent_BuS1"><p>You might have noticed it's still not that easy, cause we're not having full
cache right from the beginning, but the sum of those logarithms cannot be
expressed in a nice way, so taking the upper bound, i.e. expecting the cache
to be full at all times, is the best option for nice and readable complexity
of the whole approach.</p></div></div>
<p>Our final upper bound of this work is therefore <spanclass="katex"><spanclass="katex-mathml"><mathxmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mrow><mi>log</mi><mo></mo></mrow><mn>2</mn></msub><mi>n</mi></mrow><annotationencoding="application/x-tex">\log_2{n}</annotation></semantics></math></span><spanclass="katex-html"aria-hidden="true"><spanclass="base"><spanclass="strut"style="height:0.9386em;vertical-align:-0.2441em"></span><spanclass="mop"><spanclass="mop">lo<spanstyle="margin-right:0.01389em">g</span></span><spanclass="msupsub"><spanclass="vlist-t vlist-t2"><spanclass="vlist-r"><spanclass="vlist"style="height:0.207em"><spanstyle="top:-2.4559em;margin-right:0.05em"><spanclass="pstrut"style="height:2.7em"></span><spanclass="sizing reset-size6 size3 mtight"><spanclass="mord mtight">2</span></span></span></span><spanclass="vlist-s"></span></span><spanclass="vlist-r"><spanclass="vlist"style="height:0.2441em"><span></span></span></span></span></span></span><spanclass="mspace"style="margin-right:0.1667em"></span><spanclass="mord"><spanclass="mord mathnormal">n</span></span></span></span></span>.</p>
</li>
<li>
<p>We retrieve it from the cache. Same as in first point, but only twice, so we
get <spanclass="katex"><spanclass="katex-mathml"><mathxmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><mo>⋅</mo><msub><mrow><mi>log</mi><mo></mo></mrow><mn>2</mn></msub><mi>n</mi></mrow><annotationencoding="application/x-tex">2 \cdot \log_2{n}</annotation></semantics></math></span><spanclass="katex-html"aria-hidden="true"><spanclass="base"><spanclass="strut"style="height:0.6444em"></span><spanclass="mord">2</span><spanclass="mspace"style="margin-right:0.2222em"></span><spanclass="mbin">⋅</span><spanclass="mspace"style="margin-right:0.2222em"></span></span><spanclass="base"><spanclass="strut"style="height:0.9386em;vertical-align:-0.2441em"></span><spanclass="mop"><spanclass="mop">lo<spanstyle="margin-right:0.01389em">g</span></span><spanclass="msupsub"><spanclass="vlist-t vlist-t2"><spanclass="vlist-r"><spanclass="vlist"style="height:0.207em"><spanstyle="top:-2.4559em;margin-right:0.05em"><spanclass="pstrut"style="height:2.7em"></span><spanclass="sizing reset-size6 size3 mtight"><spanclass="mord mtight">2</span></span></span></span><spanclass="vlist-s"></span></span><spanclass="vlist-r"><spanclass="vlist"style="height:0.2441em"><span></span></span></span></span></span></span><spanclass="mspace"style="margin-right:0.1667em"></span><spanclass="mord"><spanclass="mord mathnormal">n</span></span></span></span></span>.</p>
<divclass="theme-admonition theme-admonition-caution admonition_xJq3 alert alert--warning"><divclass="admonitionHeading_Gvgb"><spanclass="admonitionIcon_Rf37"><svgviewBox="0 0 16 16"><pathfill-rule="evenodd"d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>caution</div><divclass="admonitionContent_BuS1"><p>It's done twice because of the <code>.containsKey()</code> in the <code>if</code> condition.</p></div></div>
</li>
</ol>
<p>Okay, we have evaluated work done for each of the cells in the pyramid and now
we need to put it together.</p>
<p>Let's split the time complexity of our solution into two operands:</p>
<p><spanclass="katex"><spanclass="katex-mathml"><mathxmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>r</mi></mrow><annotationencoding="application/x-tex">r</annotation></semantics></math></span><spanclass="katex-html"aria-hidden="true"><spanclass="base"><spanclass="strut"style="height:0.4306em"></span><spanclass="mord mathnormal"style="margin-right:0.02778em">r</span></span></span></span> will represent the <em>actual</em> calculation of the cells and <spanclass="katex"><spanclass="katex-mathml"><mathxmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi></mrow><annotationencoding="application/x-tex">s</annotation></semantics></math></span><spanclass="katex-html"aria-hidden="true"><spanclass="base"><spanclass="strut"style="height:0.4306em"></span><spanclass="mord mathnormal">s</span></span></span></span> will represent
the additional retrievals on top of the calculation.</p>
<p>We calculate the values only <strong>once</strong>, therefore we can safely agree on:</p>
<p>What about the <spanclass="katex"><spanclass="katex-mathml"><mathxmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi></mrow><annotationencoding="application/x-tex">s</annotation></semantics></math></span><spanclass="katex-html"aria-hidden="true"><spanclass="base"><spanclass="strut"style="height:0.4306em"></span><spanclass="mord mathnormal">s</span></span></span></span> though? Key observation here is the fact that we have 2
lookups on the tree in each of them <strong>and</strong> we do it twice, cause each cell has
<divclass="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><divclass="admonitionHeading_Gvgb"><spanclass="admonitionIcon_Rf37"><svgviewBox="0 0 12 16"><pathfill-rule="evenodd"d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><divclass="admonitionContent_BuS1"><p>You might've noticed that lookups actually take more time than the construction
of the results. This is not entirely true, since we have included the
<code>.containsKey()</code> and <code>.get()</code> from the <code>return</code> statement in the second part.</p><p>If we were to represent this more precisely, we could've gone with:</p><spanclass="katex-display"><spanclass="katex"><spanclass="katex-mathml"><mathxmlns="http://www.w3.org/1998/Math/MathML"display="block"><semantics><mtablerowspacing="0.25em"columnalign="right left"columnspacing="0em"><mtr><mtd><mstylescriptlevel="0"displaystyle="true"><mi>r</mi></mstyle></mtd><mtd><mstylescriptlevel="0"displaystyle="true"><mrow><mrow></mrow><mo>=</mo><mn>3</mn><mo>⋅</mo><mi>n</mi><mo>⋅</mo><mi>log</mi><mo></mo><mi>n</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstylescriptlevel="0"displaystyle="true"><mi>s</mi></mstyle></mtd><mtd><mstylescriptlevel="0"displaystyle="true"><mrow><mrow></mrow><mo>=</mo><mn>2</mn><mo>⋅</mo><mi>n</mi><mo>⋅</mo><mi>log</mi><mo></mo><mi>n</mi></mrow></mstyle></mtd></mtr></mtable><annotationencoding="application/x-tex">\begin{align*}
r &= 3 \cdot n \cdot \log{n} \\
s &= 2 \cdot n \cdot \log{n}
\end{align*}</annotation></semantics></math></span><spanclass="katex-html"aria-hidden="true"><spanclass="base"><spanclass="strut"style="height:3em;vertical-align:-1.25em"></span><spanclass="mord"><spanclass="mtable"><spanclass="col-align-r"><spanclass="vlist-t vlist-t2"><spanclass="vlist-r"><spanclass="vlist"style="height:1.75em"><spanstyle="top:-3.91em"><spanclass="pstrut"style="height:3em"></span><spanclass="mord"><spanclass="mord mathnormal"style="margin-right:0.02778em">r</span></span></span><spanstyle="top:-2.41em"><spanclass="pstrut"style="height:3em"></span><spanclass="mord"><spanclass="mord mathnormal">s</span></span></span></span><spanclass="vlist-s"></span></span><spanclass="vlist-r"><spanclass="vlist"style="height:1.25em"><span></span></span></span></span></span><spanclass="col-align-l"><spanclass="vlist-t vlist-t2"><spanclass="vlist-r"><spanclass="vlist"style="height:1.75em"><spanstyle="top:-3.91em"><spanclass="pstrut"style="height:3em"></span><spanclass="mord"><spanclass="mord"></span><spanclass="mspace"style="margin-right:0.2778em"></span><spanclass="mrel">=</span><spanclass="mspace"style="margin-right:0.2778em"></span><spanclass="mord">3</span><spanclass="mspace"style="margin-right:0.2222em"></span><spanclass="mbin">⋅</span><spanclass="mspace"style="margin-right:0.2222em"></span><spanclass="mord mathnormal">n</span><spanclass="mspace"style="margin-right:0.2222em"></span><spanclass="mbin">⋅</span><spanclass="mspace"style="margin-right:0.2222em"></span><spanclass="mop">lo<spanstyle="margin-right:0.01389em">g</span></span><spanclass="mspace"style="margin-right:0.1667em"></span><spanclass="mord"><spanclass="mord mathnormal">n</span></span></span></span><spanstyle="top:-2.41em"><spanclass="pstrut"style="height:3em"></span><spanclass="mord"><spanclass="mord"></span><spanclass="mspace"style="margin-right:0.2778em"></span><spanclass="mrel">=</span><spanclass="mspace"style="margin-right:0.2778em"></span><spanclass="mord">2</span><spanclass="mspace"style="margin-right:0.2222em"></span><spanclass="mbin">⋅</span><spanclass="mspace"style="margin-right:0.2222em"></span><spanclass="mord mathnormal">n</span><spanclass="mspace"style="margin-right:0.2222em"></span><spanclass="mbin">⋅</span><spanclass="mspace"style="margin-right:0.2222em"></span><spanclass="mop">lo<spanstyle="margin-right:0.01389em">g</span></span><spanclass="mspace"style="margin-right:0.1667em"></span><spanclass="mord"><spanclass="mord mathnormal">n</span></span></span></span></span><spanclass="vlist-s"></span></span><spanclass="vlist-r"><spanclass="vlist"style="height:1.25em"><span></span></span></span></span></span></span></span></span></span></span></span><p>On the other hand we are summing both numbers together, therefore in the end it
doesn't really matter.</p><p>(<em>Feel free to compare the sums of both “splits”.</em>)</p></div></div>
<p>And so our final time complexity for the whole <em>top-down dynamic programming</em>
<p>As you can see, this is worse than our <em>greedy</em> solution that was incorrect, but
it's better than the <em>naïve</em> one.</p>
<h2class="anchor anchorWithStickyNavbar_LWe7"id="memory-complexity">Memory complexity<ahref="#memory-complexity"class="hash-link"aria-label="Direct link to Memory complexity"title="Direct link to Memory complexity"></a></h2>
<p>With this approach we need to talk about the memory complexity too, because we
have introduced cache. If you think that the memory complexity is linear to the
input, you are right. We start at the top and try to find each and every slide
down. At the end we get the final result for <code>new Position(0, 0)</code>, so we need to
<p><spanclass="katex"><spanclass="katex-mathml"><mathxmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotationencoding="application/x-tex">n</annotation></semantics></math></span><spanclass="katex-html"aria-hidden="true"><spanclass="base"><spanclass="strut"style="height:0.4306em"></span><spanclass="mord mathnormal">n</span></span></span></span> represents the total amount of cells in the pyramid, i.e.</p>
<divclass="theme-admonition theme-admonition-caution admonition_xJq3 alert alert--warning"><divclass="admonitionHeading_Gvgb"><spanclass="admonitionIcon_Rf37"><svgviewBox="0 0 16 16"><pathfill-rule="evenodd"d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>caution</div><divclass="admonitionContent_BuS1"><p>If you're wondering whether it's correct because of the second <code>if</code> in our
function, your guess is right. However we are expressing the complexity in the
Bachmann-Landau notation, so we care about the <strong>upper bound</strong>, not the exact
number.</p></div></div>
<divclass="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><divclass="admonitionHeading_Gvgb"><spanclass="admonitionIcon_Rf37"><svgviewBox="0 0 12 16"><pathfill-rule="evenodd"d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Can this be optimized?</div><divclass="admonitionContent_BuS1"><p>Yes, it can! Try to think about a way, how can you minimize the memory
complexity of this approach. I'll give you a hint:</p><spanclass="katex-display"><spanclass="katex"><spanclass="katex-mathml"><mathxmlns="http://www.w3.org/1998/Math/MathML"display="block"><semantics><mrow><mimathvariant="script">O</mi><mostretchy="false">(</mo><mi>r</mi><mi>o</mi><mi>w</mi><mi>s</mi><mostretchy="false">)</mo></mrow><annotationencoding="application/x-tex">\mathcal{O}(rows)</annotation></semantics></math></span><spanclass="katex-html"aria-hidden="true"><spanclass="base"><spanclass="strut"style="height:1em;vertical-align:-0.25em"></span><spanclass="mord mathcal"style="margin-right:0.02778em">O</span><spanclass="mopen">(</span><spanclass="mord mathnormal">ro</span><spanclass="mord mathnormal"style="margin-right:0.02691em">w</span><spanclass="mord mathnormal">s</span><spanclass="mclose">)</span></span></span></span></span></div></div>
<sectiondata-footnotes="true"class="footnotes"><h2class="anchor anchorWithStickyNavbar_LWe7 sr-only"id="footnote-label">Footnotes<ahref="#footnote-label"class="hash-link"aria-label="Direct link to Footnotes"title="Direct link to Footnotes"></a></h2>
<ol>
<liid="user-content-fn-1">
<p>except the bottom row <ahref="#user-content-fnref-1"data-footnote-backref=""aria-label="Back to reference 1"class="data-footnote-backref">↩</a></p>