<ahref="https://www.codewars.com/kata/551f23362ff852e2ab000037"target="_blank"rel="noopener noreferrer">Pyramid Slide Down</a>.</p><p>We are given a 2D array of integers and we are to find the <em>slide down</em>.
<em>Slide down</em> is a maximum sum of consecutive numbers from the top to the bottom.</p><p>Let's have a look at few examples. Consider the following pyramid:</p><divclass="codeBlockContainer_Ckt0 theme-code-block"style="--prism-color:#000000;--prism-background-color:#ffffff"><divclass="codeBlockContent_biex"><pretabindex="0"class="prism-code language-text codeBlock_bY9V thin-scrollbar"><codeclass="codeBlockLines_e6Vv"><spanclass="token-line"style="color:#000000"><spanclass="token plain"> 3</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"> 7 4</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"> 2 4 6</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain">8 5 9 3</span><br></span></code></pre><divclass="buttonGroup__atx"><buttontype="button"aria-label="Copy code to clipboard"title="Copy"class="clean-btn"><spanclass="copyButtonIcons_eSgA"aria-hidden="true"><svgviewBox="0 0 24 24"class="copyButtonIcon_y97N"><pathfill="currentColor"d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svgviewBox="0 0 24 24"class="copyButtonSuccessIcon_LjdS"><pathfill="currentColor"d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>This pyramid has following slide down:</p><divclass="codeBlockContainer_Ckt0 theme-code-block"style="--prism-color:#000000;--prism-background-color:#ffffff"><divclass="codeBlockContent_biex"><pretabindex="0"class="prism-code language-text codeBlock_bY9V thin-scrollbar"><codeclass="codeBlockLines_e6Vv"><spanclass="token-line"style="color:#000000"><spanclass="token plain"> *3</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"> *7 4</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"> 2 *4 6</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain">8 5 *9 3</span><br></span></code></pre><divclass="buttonGroup__atx"><buttontype="button"aria-label="Copy code to clipboard"title="Copy"class="clean-btn"><spanclass="copyButtonIcons_eSgA"aria-hidden="true"><svgviewBox="0 0 24 24"class="copyButtonIcon_y97N"><pathfill="currentColor"d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svgviewBox="0 0 24 24"class="copyButtonSuccessIcon_LjdS"><pathfill="currentColor"d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>And its value is <code>23</code>.</p><p>We can also have a look at a <em>bigger</em> example:</p><divclass="codeBlockContainer_Ckt0 theme-code-block"style="--prism-color:#000000;--prism-background-color:#ffffff"><divclass="codeBlockContent_biex"><pretabindex="0"class="prism-code language-text codeBlock_bY9V thin-scrollbar"><codeclass="codeBlockLines_e6Vv"><spanclass="token-line"style="color:#000000"><spanclass="token plain"> 75</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"> 95 64</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"> 17 47 82</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"> 18 35 87 10</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"> 20 4 82 47 65</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"> 19 1 23 3 34</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"> 88 2 77 73 7 63 67</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"> 99 65 4 28 6 16 70 92</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"> 41 4
them in <em>Java</em><supid="fnref-1"><ahref="#fn-1"class="footnote-ref">1</a></sup>.</p></div></div><p>For all of the following solutions I will be using basic <code>main</code> function that
will output <code>true</code>/<code>false</code> based on the expected output of our algorithm. Any
other differences will lie only in the solutions of the problem. You can see the
the one with maximum sum.</p><divclass="language-java codeBlockContainer_Ckt0 theme-code-block"style="--prism-color:#000000;--prism-background-color:#ffffff"><divclass="codeBlockContent_biex"><pretabindex="0"class="prism-code language-java codeBlock_bY9V thin-scrollbar"><codeclass="codeBlockLines_e6Vv"><spanclass="token-line"style="color:#000000"><spanclass="token keyword"style="color:rgb(0, 0, 255)">public</span><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">static</span><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">int</span><spanclass="token plain"></span><spanclass="token function"style="color:rgb(0, 0, 255)">longestSlideDown</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">(</span><spanclass="token keyword"style="color:rgb(0, 0, 255)">int</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">[</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">]</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">[</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">]</span><spanclass="token plain"> pyramid</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">,</span><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">int</span><spanclass="token plain"> row</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">,</span><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">int</span><spanclass="token plain"> col</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">)</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">{</span><spanclass="token plain"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">if</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">(</span><spanclass="token plain">row </span><spanclass="token operator"style="color:rgb(0, 0, 0)">>=</span><spanclass="token plain"> pyramid</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">.</span><spanclass="token plain">length </span><spanclass="token operator"style="color:rgb(0, 0, 0)">||</span><spanclass="token plain"> col </span><spanclass="token operator"style="color:rgb(0, 0, 0)"><</span><spanclass="token plain"></span><spanclass="token number"style="color:rgb(9, 134, 88)">0</span><spanclass="token plain"></span><spanclass="token operator"style="color:rgb(0, 0, 0)">||</span><spanclass="token plain"> col </span><spanclass="token operator"style="color:rgb(0, 0, 0)">>=</span><spanclass="token plain"> pyramid</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">[</span><spanclass="token plain">row</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">]</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">.</span><spanclass="token plain">length</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">)</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">{</span><spanclass="token plain"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"></span><spanclass="token comment"style="color:rgb(0, 128, 0)">// BASE: We have gotten out of bounds, there's no reasonable value to</span><spanclass="token plain"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"></span><spanclass="token comment"style="color:rgb(0, 128, 0)">// return, so we just return the ‹MIN_VALUE› to ensure that it cannot</span><spanclass="token plain"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"></span><spanclass="token comment"style="color:rgb(0, 128, 0)">// be maximum.</span><spanclass="tokenplai
pyramid itself. Second one is the recursive “algorithm” that finds the slide
down.</p><p>It is a relatively simple solution… There's nothing to do at the bottom of the
pyramid, so we just return the value in the <em>cell</em>. Otherwise we add it and try
to slide down the available cells below the current row.</p><h3class="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></h3><p>If you get the source code and run it yourself, it runs rather fine… I hope you
are wondering about the time complexity of the proposed solution and, since it
really is a naïve solution, the time complexity is pretty bad. Let's find the
worst case scenario.</p><p>Let's start with the first overload:</p><divclass="language-java codeBlockContainer_Ckt0 theme-code-block"style="--prism-color:#000000;--prism-background-color:#ffffff"><divclass="codeBlockContent_biex"><pretabindex="0"class="prism-code language-java codeBlock_bY9V thin-scrollbar"><codeclass="codeBlockLines_e6Vv"><spanclass="token-line"style="color:#000000"><spanclass="token keyword"style="color:rgb(0, 0, 255)">public</span><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">static</span><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">int</span><spanclass="token plain"></span><spanclass="token function"style="color:rgb(0, 0, 255)">longestSlideDown</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">(</span><spanclass="token keyword"style="color:rgb(0, 0, 255)">int</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">[</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">]</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">[</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">]</span><spanclass="token plain"> pyramid</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">)</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">{</span><spanclass="token plain"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">return</span><spanclass="token plain"></span><spanclass="token function"style="color:rgb(0, 0, 255)">longestSlideDown</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">(</span><spanclass="token plain">pyramid</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">,</span><spanclass="token plain"></span><spanclass="token number"style="color:rgb(9, 134, 88)">0</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">,</span><spanclass="token plain"></span><spanclass="token number"style="color:rgb(9, 134, 88)">0</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">)</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">;</span><spanclass="token plain"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><divclass="buttonGroup__atx"><buttontype="button"aria-label="Copy code to clipboard"title="Copy"class="clean-btn"><spanclass="copyButtonIcons_eSgA"aria-hidden="true"><svgviewBox="0 0 24 24"class="copyButtonIcon_y97N"><pathfill="currentColor"d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svgviewBox="0 0 24 24"class="copyButtonSuccessIcon_LjdS"><pathfill="currentColor"d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>There's not much to do here, so we can safely say that the time complexity of
this function is bounded by <spanclass="math math-inline"><spanclass="katex"><spanclass="katex-mathml"><mathxmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mostretchy="false">(</mo><mi>n</mi><mostretchy="false">)</mo></mrow><annotationencoding="application/x-tex">T(n)</annotation></semantics></math></span><spanclass="katex-html"aria-hidden="true"><spanclass="base"><spanclass="strut"style="height:1em;vertical-align:-0.25em"></span><spanclass="mord mathnormal"style="margin-right:0.13889em">T</span><spanclass="mopen">(</span><spanclass="mord mathnormal">n</span><spanclass="mclose">)</span></span></span></span></span>, where <spanclass="math math-inline"><spanclass="katex"><spanclass="katex-mathml"><mathxmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi></mrow><annotationencoding="application/x-tex">T</annotation></semantics></math></span><spanclass="katex-html"aria-hidden="true"><spanclass="base"><spanclass="strut"style="height:0.6833em"></span><spanclass="mord mathnormal"style="margin-right:0.13889em">T</span></span></span></span></span> is our second overload. This
doesn't tell us anything, so let's move on to the second overload where we are
and nothing else. Let's dissect them!</p><p>First <code>return</code> statement is the base case, so it has a constant time complexity.</p><p>Second one a bit tricky. We add two numbers together, which we'll consider as
constant, but for the right part of the expression we take maximum from the left
and right paths. OK… So what happens? We evaluate the <code>longestSlideDown</code> while
choosing the under and right both. They are separate computations though, so we
are branching from each call of <code>longestSlideDown</code>, unless it's a base case.</p><p>What does that mean for us then? We basically get</p><divclass="math math-display"><spanclass="katex-display"><spanclass="katex"><spanclass="katex-mathml"><mathxmlns="http://www.w3.org/1998/Math/MathML"display="block"><semantics><mrow><mi>T</mi><mostretchy="false">(</mo><mi>y</mi><mostretchy="false">)</mo><mo>=</mo><mrow><mofence="true">{</mo><mtablerowspacing="0.36em"columnalign="left left"columnspacing="1em"><mtr><mtd><mstylescriptlevel="0"displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstylescriptlevel="0"displaystyle="false"><mrow><mtext>,if</mtext><mi>y</mi><mo>=</mo><mi>r</mi><mi>o</mi><mi>w</mi><mi>s</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstylescriptlevel="0"displaystyle="false"><mrow><mn>1</mn><mo>+</mo><mn>2</mn><mo>⋅</mo><mi>T</mi><mostretchy="false">(</mo><mi>y</mi><mo>+</mo><mn>1</mn><mostretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstylescriptlevel="0"displaystyle="false"><mtext>,otherwise</mtext></mstyle></mtd></mtr></mtable></mrow></mrow><annotationencoding="application/x-tex">T(y) = \begin{cases} 1 & \text{, if } y = rows \\ 1 + 2 \cdot T(y + 1) & \text{, otherwise} \end{cases}</annotation></semantics></math></span><spanclass="katex-html"aria-hidden="true"><spanclass="base"><spanclass="strut"style="height:1em;vertical-align:-0.25em"></span><spanclass="mord mathnormal"style="margin-right:0.13889em">T</span><spanclass="mopen">(</span><spanclass="mord mathnormal"style="margin-right:0.03588em">y</span><spanclass="mclose">)</span><spanclass="mspace"style="margin-right:0.2778em"></span><spanclass="mrel">=</span><spanclass="mspace"style="margin-right:0.2778em"></span></span><spanclass="base"><spanclass="strut"style="height:3em;vertical-align:-1.25em"></span><spanclass="minner"><spanclass="mopen delimcenter"style="top:0em"><spanclass="delimsizing size4">{</span></span><spanclass="mord"><spanclass="mtable"><spanclass="col-align-l"><spanclass="vlist-t vlist-t2"><spanclass="vlist-r"><spanclass="vlist"style="height:1.69em"><spanstyle="top:-3.69em"><spanclass="pstrut"style="height:3.008em"></span><spanclass="mord"><spanclass="mord">1</span></span></span><spanstyle="top:-2.25em"><spanclass="pstrut"style="height:3.008em"></span><spanclass="mord"><spanclass="mord">1</span><spanclass="mspace"style="margin-right:0.2222em"></span><spanclass="mbin">+</span><spanclass="mspace"style="margin-right:0.2222em"></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"style="margin-right:0.13889em">T</span><spanclass="mopen">(</span><spanclass="mord mathnormal"style="margin-right:0.03588em">y</span><spanclass="mspace"style="margin-right:0.2222em"></span><spanclass="mbin">+</span><spanclass="mspace"style="margin-right:0.2222em"></span><spanclass="mord">1</span><spanclass="mclose">)</span></span></span></span><spanclass="vlist-s"></span></span><spanclass="vlist-r"><spanclass="vlist"style="height:1.19em"><span></span></span></span></span></span><spanclass="arraycolsep"style="width:1em"></span><spanclass="col-align-l"><spanclass="vlist-t vlist-t2"><spanclass="vlist-r"><spanclass="vlist"style="height:1.69em"><spanstyle="top:-3.69em"><spanclass="pstrut"style="height:3.008em"></span><spanclass="mord"><spanclass="mord text"><spanclass="mord">,if</span></span><spanclass="mord mathnormal"style="margin-right:0.03588em">y</span><spanclass="mspace"style="margin-right:0.2778em"></span><spanclass="mrel">=</span><spanclass="mspace"style="margin-right:0.2778em"></span><spanclass="mord mathnormal">ro</span><spanclass="mord mathnormal"style="margin-right:0.02691em">w</span><spanclass="mord mathnormal">s</span></span></span><spanstyle="top:-2.25em"><spanclass="pstrut"style="height:3.008em"></span><spanclass="mord"><spanclass="mord text"><spanclass="mord">,
regardless of being in the base case. Those are the <code>1</code>s in both cases.</li><li>If we are not in the base case, we move one row down <strong>twice</strong>. That's how we
obtained <code>2 *</code> and <code>y + 1</code> in the <em>otherwise</em> case.</li><li>We move row-by-row, so we move down <code>y</code>-times and each call splits to two
subtrees.</li><li>Overall, if we were to represent the calls as a tree, we would get a full
binary tree of height <code>y</code>, in each node we do some work in constant time,
therefore we can just sum the ones.</li></ol><divclass="theme-admonition theme-admonition-warning alert alert--danger admonition_LlT9"><divclass="admonitionHeading_tbUL"><spanclass="admonitionIcon_kALy"><svgviewBox="0 0 12 16"><pathfill-rule="evenodd"d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>danger</div><divclass="admonitionContent_S0QG"><p>It would've been more complicated to get an exact result. In the equation above
we are assuming that the width of the pyramid is bound by the height.</p></div></div><p>Hopefully we can agree that this is not the best we can do. 😉</p><h2class="anchor anchorWithStickyNavbar_LWe7"id="greedy-solution">Greedy solution<ahref="#greedy-solution"class="hash-link"aria-label="Direct link to Greedy solution"title="Direct link to Greedy solution"></a></h2><p>We will try to optimize it a bit. Let's start with a relatively simple <em>greedy</em>
approach.</p><divclass="theme-admonition theme-admonition-info alert alert--info admonition_LlT9"><divclass="admonitionHeading_tbUL"><spanclass="admonitionIcon_kALy"><svgviewBox="0 0 14 16"><pathfill-rule="evenodd"d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>Greedy algorithms</div><divclass="admonitionContent_S0QG"><p><em>Greedy algorithms</em> can be described as algorithms that decide the action on the
optimal option at the moment.</p></div></div><p>We can try to adjust the naïve solution. The most problematic part are the
we simply go left.</p><h3class="anchor anchorWithStickyNavbar_LWe7"id="time-complexity-1">Time complexity<ahref="#time-complexity-1"class="hash-link"aria-label="Direct link to Time complexity"title="Direct link to Time complexity"></a></h3><p>We have switched from <em>adding the maximum</em> to <em>following the “bigger” path</em>, so
we improved the time complexity tremendously. We just go down the pyramid all
the way to the bottom. Therefore we are getting:</p><divclass="math math-display"><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><p>We have managed to convert our exponential solution into a linear one.</p><h3class="anchor anchorWithStickyNavbar_LWe7"id="running-the-tests">Running the tests<ahref="#running-the-tests"class="hash-link"aria-label="Direct link to Running the tests"title="Direct link to Running the tests"></a></h3><p>However, if we run the tests, we notice that the second test failed:</p><divclass="codeBlockContainer_Ckt0 theme-code-block"style="--prism-color:#000000;--prism-background-color:#ffffff"><divclass="codeBlockContent_biex"><pretabindex="0"class="prism-code language-text codeBlock_bY9V thin-scrollbar"><codeclass="codeBlockLines_e6Vv"><spanclass="token-line"style="color:#000000"><spanclass="token plain">Test #1: passed</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain">Test #2: failed</span><br></span></code></pre><divclass="buttonGroup__atx"><buttontype="button"aria-label="Copy code to clipboard"title="Copy"class="clean-btn"><spanclass="copyButtonIcons_eSgA"aria-hidden="true"><svgviewBox="0 0 24 24"class="copyButtonIcon_y97N"><pathfill="currentColor"d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svgviewBox="0 0 24 24"class="copyButtonSuccessIcon_LjdS"><pathfill="currentColor"d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>What's going on? Well, we have improved the time complexity, but greedy
algorithms are not the ideal solution to <strong>all</strong> problems. In this case there
may be a solution that is bigger than the one found using the greedy algorithm.</p><p>Imagine the following pyramid:</p><divclass="codeBlockContainer_Ckt0 theme-code-block"style="--prism-color:#000000;--prism-background-color:#ffffff"><divclass="codeBlockContent_biex"><pretabindex="0"class="prism-code language-text codeBlock_bY9V thin-scrollbar"><codeclass="codeBlockLines_e6Vv"><spanclass="token-line"style="color:#000000"><spanclass="token plain"> 1</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"> 2 3</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"> 5 6 7</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"> 8 9 10 11</span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain">99 13 14 15 16</span><br></span></code></pre><divclass="buttonGroup__atx"><buttontype="button"aria-label="Copy code to clipboard"title="Copy"class="clean-btn"><spanclass="copyButtonIcons_eSgA"aria-hidden="true"><svgviewBox="0 0 24 24"class="copyButtonIcon_y97N"><pathfill="currentColor"d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svgviewBox="0 0 24 24"class="copyButtonSuccessIcon_LjdS"><pathfill="currentColor"d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>We start at the top:</p><ol><li>Current cell: <code>1</code>, we can choose from <code>2</code> and <code>3</code>, <code>3</code> looks better, so we
choose it.</li><li>Current cell: <code>3</code>, we can choose from <code>6</code> and <code>7</code>, <code>7</code> looks better, so we
choose it.</li><li>Current cell: <code>7</code>, we can choose from <code>10</code> and <code>11</code>, <code>11</code> looks better, so we
choose it.</li><li>Current cell: <code>11</code>, we can choose from <code>15</code> and <code>16</code>, <code>16</code> looks better, so
we choose it.</li></ol><p>Our final sum is: <code>1 + 3 + 7 + 11 + 16 = 38</code>, but in the bottom left cell we
have a <code>99</code> that is bigger than our whole sum.</p><divclass="theme-admonition theme-admonition-tip alert alert--success admonition_LlT9"><divclass="admonitionHeading_tbUL"><spanclass="admonitionIcon_kALy"><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_S0QG"><p>Dijkstra's algorithm is a greedy algorithm too, try to think why it is correct.</p></div></div><h2class="anchor anchorWithStickyNavbar_LWe7"id="top-down-dp">Top-down DP<ahref="#top-down-dp"class="hash-link"aria-label="Direct link to Top-down DP"title="Direct link to Top-down DP"></a></h2><p><em>Top-down dynamic programming</em> is probably the most common approach, since (at
least looks like) is the easiest to implement. The whole point is avoiding the
unnecessary computations that we have already done.</p><p>In our case, we can use our naïve solution and put a <em>cache</em> on top of it that
will make sure, we don't do unnecessary calculations.</p><divclass="language-java codeBlockContainer_Ckt0 theme-code-block"style="--prism-color:#000000;--prism-background-color:#ffffff"><divclass="codeBlockContent_biex"><pretabindex="0"class="prism-code language-java codeBlock_bY9V thin-scrollbar"><codeclass="codeBlockLines_e6Vv"><spanclass="token-line"style="color:#000000"><spanclass="token comment"style="color:rgb(0, 128, 0)">// This “structure” is required, since I have decided to use ‹TreeMap› which</span><spanclass="token plain"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"></span><spanclass="token comment"style="color:rgb(0, 128, 0)">// requires the ordering on the keys. It represents one position in the pyramid.</span><spanclass="token plain"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">record</span><spanclass="token plain"></span><spanclass="token class-name"style="color:rgb(38, 127, 153)">Position</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">(</span><spanclass="token keyword"style="color:rgb(0, 0, 255)">int</span><spanclass="token plain"> row</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">,</span><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">int</span><spanclass="token plain"> col</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">)</span><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">implements</span><spanclass="token plain"></span><spanclass="token class-name"style="color:rgb(38, 127, 153)">Comparable</span><spanclass="token generics punctuation"style="color:rgb(4, 81, 165)"><</span><spanclass="token generics class-name"style="color:rgb(38, 127, 153)">Position</span><spanclass="token generics punctuation"style="color:rgb(4, 81, 165)">></span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">{</span><spanclass="token plain"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">public</span><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">int</span><spanclass="token plain"></span><spanclass="token function"style="color:rgb(0, 0, 255)">compareTo</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">(</span><spanclass="token class-name"style="color:rgb(38, 127, 153)">Position</span><spanclass="token plain"> r</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">)</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">{</span><spanclass="token plain"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">if</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">(</span><spanclass="token plain">row </span><spanclass="token operator"style="color:rgb(0, 0, 0)">!=</span><spanclass="token plain"> r</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">.</span><spanclass="token plain">row</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">)</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">{</span><spanclass="token plain"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">return</span><spanclass="token plain"></span><spanclass="token class-name"style="color:rgb(38, 127, 153)">Integer</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">.</span><spanclass="token function"style="color:rgb(0, 0, 255)">valueOf</span><spanclass=
caching the already computed values, we need a “reasonable” key. In this case we
share the cache only for one <em>run</em> (i.e. pyramid) of the <code>longestSlideDown</code>, so
we can cache just with the indices within the pyramid, i.e. the <code>Position</code>.</p><divclass="theme-admonition theme-admonition-tip alert alert--success admonition_LlT9"><divclass="admonitionHeading_tbUL"><spanclass="admonitionIcon_kALy"><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>Record</div><divclass="admonitionContent_S0QG"><p><em>Record</em> is relatively new addition to the Java language. It is basically an
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><h3class="anchor anchorWithStickyNavbar_LWe7"id="time-complexity-2">Time complexity<ahref="#time-complexity-2"class="hash-link"aria-label="Direct link to Time complexity"title="Direct link to Time complexity"></a></h3><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<supid="fnref-2"><ahref="#fn-2"class="footnote-ref">2</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="math math-inline"><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></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 alert alert--warning admonition_LlT9"><divclass="admonitionHeading_tbUL"><spanclass="admonitionIcon_kALy"><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_S0QG"><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="math math-inline"><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></span>.</p></li><li><p>We retrieve it from the cache. Same as in first point, but only twice, so we
get <spanclass="math math-inline"><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></span>. </p><divclass="theme-admonition theme-admonition-caution alert alert--warning admonition_LlT9"><divclass="admonitionHeading_tbUL"><spanclass="admonitionIcon_kALy"><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_S0QG"><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><divclass="math math-display"><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><mo>+</mo><mi>s</mi><mostretchy="false">)</mo></mrow><annotationencoding="application/x-tex">\mathcal{O}(r + s)</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"style="margin-right:0.02778em">r</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:1em;vertical-align:-0.25em"></span><spanclass="mord mathnormal">s</span><spanclass="mclose">)</span></span></span></span></span></div><p><spanclass="math math-inline"><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></span> will represent the <em>actual</em> calculation of the cells and <spanclass="math math-inline"><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></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><divclass="math math-display"><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><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 &= n \cdot \log{n} \\ \end{align*}</annotation></semantics></math></span><spanclass="katex-html"aria-hidden="true"><spanclass="base"><spanclass="strut"style="height:1.5em;vertical-align:-0.5em"></span><spanclass="mord"><spanclass="mtable"><spanclass="col-align-r"><spanclass="vlist-t vlist-t2"><spanclass="vlist-r"><spanclass="vlist"style="height:1em"><spanstyle="top:-3.16em"><spanclass="pstrut"style="height:3em"></span><spanclass="mord"><spanclass="mord mathnormal"style="margin-right:0.02778em">r</span></span></span></span><spanclass="vlist-s"></span></span><spanclass="vlist-r"><spanclass="vlist"style="height:0.5em"><span></span></span></span></span></span><spanclass="col-align-l"><spanclass="vlist-t vlist-t2"><spanclass="vlist-r"><spanclass="vlist"style="height:1em"><spanstyle="top:-3.16em"><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 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:0.5em"><span></span></span></span></span></span></span></span></span></span></span></span></div><p>What about the <spanclass="math math-inline"><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></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
at most 2 parents:</p><divclass="math math-display"><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>s</mi></mstyle></mtd><mtd><mstylescriptlevel="0"displaystyle="true"><mrow><mrow></mrow><mo>=</mo><mi>n</mi><mo>⋅</mo><mn>2</mn><mo>⋅</mo><mrow><mofence="true">(</mo><mn>2</mn><mo>⋅</mo><mi>log</mi><mo></mo><mi>n</mi><mofence="true">)</mo></mrow></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>4</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*} s &= n \cdot 2 \cdot \left( 2 \cdot \log{n} \right) \\ s &= 4 \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">s</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 mathnormal">n</span><spanclass="mspace"style="margin-right:0.2222em"></span><spanclass="mbin">⋅</span><spanclass="mspace"style="margin-right:0.2222em"></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="minner"><spanclass="mopen delimcenter"style="top:0em">(</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="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><spanclass="mclose delimcenter"style="top:0em">)</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">4</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></s
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><divclass="math math-display"><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></div><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>
it's better than the <em>naïve</em> one.</p><h3class="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></h3><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
compute everything below.</p><p>That's how we obtain:</p><divclass="math math-display"><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>n</mi><mostretchy="false">)</mo></mrow><annotationencoding="application/x-tex">\mathcal{O}(n)</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">n</span><spanclass="mclose">)</span></span></span></span></span></div><p><spanclass="math math-inline"><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></span> represents the total amount of cells in the pyramid, i.e.</p><divclass="math math-display"><spanclass="katex-display"><spanclass="katex"><spanclass="katex-mathml"><mathxmlns="http://www.w3.org/1998/Math/MathML"display="block"><semantics><mrow><munderover><mo>∑</mo><mrow><mi>y</mi><mo>=</mo><mn>0</mn></mrow><mrow><mrow><mimathvariant="monospace">p</mi><mimathvariant="monospace">y</mi><mimathvariant="monospace">r</mi><mimathvariant="monospace">a</mi><mimathvariant="monospace">m</mi><mimathvariant="monospace">i</mi><mimathvariant="monospace">d</mi><mimathvariant="monospace">.</mi><mimathvariant="monospace">l</mi><mimathvariant="monospace">e</mi><mimathvariant="monospace">n</mi><mimathvariant="monospace">g</mi><mimathvariant="monospace">t</mi><mimathvariant="monospace">h</mi></mrow><mo>−</mo><mn>1</mn></mrow></munderover><mrow><mimathvariant="monospace">p</mi><mimathvariant="monospace">y</mi><mimathvariant="monospace">r</mi><mimathvariant="monospace">a</mi><mimathvariant="monospace">m</mi><mimathvariant="monospace">i</mi><mimathvariant="monospace">d</mi></mrow><mrow><mofence="true">[</mo><mi>y</mi><mofence="true">]</mo></mrow><mrow><mimathvariant="monospace">.</mi><mimathvariant="monospace">l</mi><mimathvariant="monospace">e</mi><mimathvariant="monospace">n</mi><mimathvariant="monospace">g</mi><mimathvariant="monospace">t</mi><mimathvariant="monospace">h</mi></mrow></mrow><annotationencoding="application/x-tex">\sum_{y=0}^{\mathtt{pyramid.length} - 1} \mathtt{pyramid}\left[y\right]\mathtt{.length}</annotation></semantics></math></span><spanclass="katex-html"aria-hidden="true"><spanclass="base"><spanclass="strut"style="height:3.2709em;vertical-align:-1.4032em"></span><spanclass="mop op-limits"><spanclass="vlist-t vlist-t2"><spanclass="vlist-r"><spanclass="vlist"style="height:1.8677em"><spanstyle="top:-1.8829em;margin-left:0em"><spanclass="pstrut"style="height:3.05em"></span><spanclass="sizing reset-size6 size3 mtight"><spanclass="mord mtight"><spanclass="mord mathnormal mtight"style="margin-right:0.03588em">y</span><spanclass="mrel mtight">=</span><spanclass="mord mtight">0</span></span></span></span><spanstyle="top:-3.05em"><spanclass="pstrut"style="height:3.05em"></span><span><spanclass="mop op-symbol large-op">∑</span></span></span><spanstyle="top:-4.3666em;margin-left:0em"><spanclass="pstrut"style="height:3.05em"></span><spanclass="sizing reset-size6 size3 mtight"><spanclass="mord mtight"><spanclass="mord mtight"><spanclass="mord mathtt mtight">pyramid.length</span></span><spanclass="mbin mtight">−</span><spanclass="mord mtight">1</span></span></span></span></span><spanclass="vlist-s"></span></span><spanclass="vlist-r"><spanclass="vlist"style="height:1.4032em"><span></span></span></span></span></span><spanclass="mspace"style="margin-right:0.1667em"></span><span
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 alert alert--success admonition_LlT9"><divclass="admonitionHeading_tbUL"><spanclass="admonitionIcon_kALy"><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_S0QG"><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><divclass="math math-display"><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></div><h2class="anchor anchorWithStickyNavbar_LWe7"id="bottom-up-dp">Bottom-up DP<ahref="#bottom-up-dp"class="hash-link"aria-label="Direct link to Bottom-up DP"title="Direct link to Bottom-up DP"></a></h2><p>If you try to think in depth about the top-down DP solution, you might notice
that the <em>core</em> of it stands on caching the calculations that have been already
done on the lower “levels” of the pyramid. Our bottom-up implementation will be
using this fact!</p><divclass="theme-admonition theme-admonition-tip alert alert--success admonition_LlT9"><divclass="admonitionHeading_tbUL"><spanclass="admonitionIcon_kALy"><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_S0QG"><p>As I have said in the <em>top-down DP</em> section, it is the easiest way to implement
DP (unless the cached function has complicated parameters, in that case it might
get messy).</p><p>Bottom-up dynamic programming can be more effective, but may be more complicated
to implement right from the beginning.</p></div></div><p>Let's see how we can implement it:</p><divclass="language-java codeBlockContainer_Ckt0 theme-code-block"style="--prism-color:#000000;--prism-background-color:#ffffff"><divclass="codeBlockContent_biex"><pretabindex="0"class="prism-code language-java codeBlock_bY9V thin-scrollbar"><codeclass="codeBlockLines_e6Vv"><spanclass="token-line"style="color:#000000"><spanclass="token keyword"style="color:rgb(0, 0, 255)">public</span><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">static</span><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">int</span><spanclass="token plain"></span><spanclass="token function"style="color:rgb(0, 0, 255)">longestSlideDown</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">(</span><spanclass="token keyword"style="color:rgb(0, 0, 255)">int</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">[</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">]</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">[</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">]</span><spanclass="token plain"> pyramid</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">)</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">{</span><spanclass="token plain"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"></span><spanclass="token comment"style="color:rgb(0, 128, 0)">// In the beginning we declare new array. At this point it is easier to just</span><spanclass="token plain"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"></span><spanclass="token comment"style="color:rgb(0, 128, 0)">// work with the one dimension, i.e. just allocating the space for the rows.</span><spanclass="token plain"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">int</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">[</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">]</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">[</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">]</span><spanclass="token plain"> slideDowns </span><spanclass="token operator"style="color:rgb(0, 0, 0)">=</span><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">new</span><spanclass="token plain"></span><spanclass="token keyword"style="color:rgb(0, 0, 255)">int</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">[</span><spanclass="token plain">pyramid</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">.</span><spanclass="token plain">length</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">]</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">[</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">]</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">;</span><spanclass="token plain"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"style="display:inline-block"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"></span><spanclass="token comment"style="color:rgb(0, 128, 0)">// Bottom row gets just copied, there's nothing else to do… It's the base</span><spanclass="token plain"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"></span><spanclass="token comment"style="color:rgb(0, 128, 0)">// case.</span><spanclass="token plain"></span><br></span><spanclass="token-line"style="color:#000000"><spanclass="token plain"> slideDowns</span><spanclass="token punctuation"style="color:rgb(4, 81, 165)">[</span><spanclass="token
might be more beneficial to see right next to the “offending” lines.</p><p>As you can see, in this approach we go from the other side<supid="fnref-3"><ahref="#fn-3"class="footnote-ref">3</a></sup>, the bottom of
the pyramid and propagate the partial results up.</p><divclass="theme-admonition theme-admonition-info alert alert--info admonition_LlT9"><divclass="admonitionHeading_tbUL"><spanclass="admonitionIcon_kALy"><svgviewBox="0 0 14 16"><pathfill-rule="evenodd"d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span><mdxadmonitiontitle>How is this different from the <em>greedy</em> solution???</mdxadmonitiontitle></div><divclass="admonitionContent_S0QG"><p>If you try to compare them, you might find a very noticable difference. The
greedy approach is going from the top to the bottom without <strong>any</strong> knowledge of
what's going on below. On the other hand, bottom-up DP is going from the bottom
(<em>DUH…</em>) and <strong>propagates</strong> the partial results to the top. The propagation is
what makes sure that at the top I don't choose the best <strong>local</strong> choice, but
the best <strong>overall</strong> result I can achieve.</p></div></div><h3class="anchor anchorWithStickyNavbar_LWe7"id="time-complexity-3">Time complexity<ahref="#time-complexity-3"class="hash-link"aria-label="Direct link to Time complexity"title="Direct link to Time complexity"></a></h3><p>Time complexity of this solution is rather simple. We allocate an array for the
rows and then for each row, we copy it and adjust the partial results. Doing
this we get:</p><divclass="math math-display"><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><mo>+</mo><mn>2</mn><mi>n</mi><mostretchy="false">)</mo></mrow><annotationencoding="application/x-tex">\mathcal{O}(rows + 2n)</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="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:1em;vertical-align:-0.25em"></span><spanclass="mord">2</span><spanclass="mord mathnormal">n</span><spanclass="mclose">)</span></span></span></span></span></div><p>Of course, this is an upper bound, since we iterate through the bottom row only
once.</p><h3class="anchor anchorWithStickyNavbar_LWe7"id="memory-complexity-1">Memory complexity<ahref="#memory-complexity-1"class="hash-link"aria-label="Direct link to Memory complexity"title="Direct link to Memory complexity"></a></h3><p>We're allocating an array for the pyramid <strong>again</strong> for our partial results, so
we get:</p><divclass="math math-display"><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>n</mi><mostretchy="false">)</mo></mrow><annotationencoding="application/x-tex">\mathcal{O}(n)</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">n</span><spanclass="mclose">)</span></span></span></span></span></div><divclass="theme-admonition theme-admonition-tip alert alert--success admonition_LlT9"><divclass="admonitionHeading_tbUL"><spanclass="admonitionIcon_kALy"><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_S0QG"><p>If we were writing this in C++ or Rust, we could've avoided that, but not
really.</p><p>C++ would allow us to <strong>copy</strong> the pyramid rightaway into the parameter, so we
would be able to directly change it. However it's still a copy, even though we
don't need to allocate anything ourselves. It's just implicitly done for us.</p><p>Rust is more funny in this case. If the pyramids weren't used after the call of
<code>longest_slide_down</code>, it would simply <strong>move</strong> them into the functions. If they
were used afterwards, the compiler would force you to either borrow it, or
<em>clone-and-move</em> for the function.</p><hr><p>Since we're doing it in Java, we get a reference to the <em>original</em> array and we
can't do whatever we want with it.</p></div></div><h2class="anchor anchorWithStickyNavbar_LWe7"id="summary">Summary<ahref="#summary"class="hash-link"aria-label="Direct link to Summary"title="Direct link to Summary"></a></h2><p>And we've finally reached the end. We have seen 4 different “solutions”<supid="fnref-4"><ahref="#fn-4"class="footnote-ref">4</a></sup> of
the same problem using different approaches. Different approaches follow the
order in which you might come up with them, each approach influences its
successor and represents the way we can enhance the existing implementation.</p><hr><divclass="theme-admonition theme-admonition-info alert alert--info admonition_LlT9"><divclass="admonitionHeading_tbUL"><spanclass="admonitionIcon_kALy"><svgviewBox="0 0 14 16"><pathfill-rule="evenodd"d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>source</div><divclass="admonitionContent_S0QG"><p>You can find source code referenced in the text