"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[2619],{4457:(s,e,n)=>{n.r(e),n.d(e,{assets:()=>c,contentTitle:()=>t,default:()=>o,frontMatter:()=>l,metadata:()=>r,toc:()=>m});var a=n(5893),i=n(1151);const l={id:"pyramid-slide-down",title:"Introduction to dynamic programming",description:"Solving a problem in different ways.\n",tags:["java","recursion","exponential","greedy","dynamic-programming","top-down-dp","bottom-up-dp"],last_updated:{date:new Date("2023-08-17T00:00:00.000Z")}},t=void 0,r={id:"recursion/pyramid-slide-down",title:"Introduction to dynamic programming",description:"Solving a problem in different ways.\n",source:"@site/algorithms/04-recursion/2023-08-17-pyramid-slide-down.md",sourceDirName:"04-recursion",slug:"/recursion/pyramid-slide-down",permalink:"/algorithms/recursion/pyramid-slide-down",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/algorithms/04-recursion/2023-08-17-pyramid-slide-down.md",tags:[{label:"java",permalink:"/algorithms/tags/java"},{label:"recursion",permalink:"/algorithms/tags/recursion"},{label:"exponential",permalink:"/algorithms/tags/exponential"},{label:"greedy",permalink:"/algorithms/tags/greedy"},{label:"dynamic-programming",permalink:"/algorithms/tags/dynamic-programming"},{label:"top-down-dp",permalink:"/algorithms/tags/top-down-dp"},{label:"bottom-up-dp",permalink:"/algorithms/tags/bottom-up-dp"}],version:"current",lastUpdatedAt:1700847079,formattedLastUpdatedAt:"Nov 24, 2023",frontMatter:{id:"pyramid-slide-down",title:"Introduction to dynamic programming",description:"Solving a problem in different ways.\n",tags:["java","recursion","exponential","greedy","dynamic-programming","top-down-dp","bottom-up-dp"],last_updated:{date:"2023-08-17T00:00:00.000Z"}},sidebar:"autogeneratedBar",previous:{title:"Recursion and backtracking with Robot Karel",permalink:"/algorithms/recursion/karel-1"},next:{title:"Red-Black Trees",permalink:"/algorithms/category/red-black-trees"}},c={},m=[{value:"Problem",id:"problem",level:2},{value:"Solving the problem",id:"solving-the-problem",level:2},{value:"Na\xefve solution",id:"na\xefve-solution",level:2},{value:"Time complexity",id:"time-complexity",level:3},{value:"Greedy solution",id:"greedy-solution",level:2},{value:"Time complexity",id:"time-complexity-1",level:3},{value:"Running the tests",id:"running-the-tests",level:3},{value:"Top-down DP",id:"top-down-dp",level:2},{value:"Time complexity",id:"time-complexity-2",level:3},{value:"Memory complexity",id:"memory-complexity",level:3},{value:"Bottom-up DP",id:"bottom-up-dp",level:2},{value:"Time complexity",id:"time-complexity-3",level:3},{value:"Memory complexity",id:"memory-complexity-1",level:3},{value:"Summary",id:"summary",level:2}];function h(s){const e={a:"a",admonition:"admonition",annotation:"annotation",code:"code",em:"em",h2:"h2",h3:"h3",hr:"hr",li:"li",math:"math",mdxAdmonitionTitle:"mdxAdmonitionTitle",mi:"mi",mn:"mn",mo:"mo",mrow:"mrow",mspace:"mspace",mstyle:"mstyle",msub:"msub",msup:"msup",mtable:"mtable",mtd:"mtd",mtext:"mtext",mtr:"mtr",munderover:"munderover",ol:"ol",p:"p",pre:"pre",section:"section",semantics:"semantics",span:"span",strong:"strong",sup:"sup",...(0,i.a)(),...s.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(e.p,{children:"In this post we will try to solve one problem in different ways."}),"\n",(0,a.jsx)(e.h2,{id:"problem",children:"Problem"}),"\n",(0,a.jsxs)(e.p,{children:["The problem we are going to solve is one of ",(0,a.jsx)(e.em,{children:"CodeWars"})," katas and is called\n",(0,a.jsx)(e.a,{href:"https://www.codewars.com/kata/551f23362ff852e2ab000037",children:"Pyramid Slide Down"}),"."]}),"\n",(0,a.jsxs)(e.p,{children:["We are given a 2D array of integers and we are to find the ",(0,a.jsx)(e.em,{children:"slide down"}),".\n",(0,a.jsx)(e.em,{children:"Slide down"})," is a maximum sum of consecutive numbers from the top to the bottom."]}),"\n",(0,a.jsx)(e.p,{children:"Let's have a look at few examples. Consider the following pyramid:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{children:" 3\n 7 4\n 2 4 6\n8 5 9 3\n"})}),"\n",(0,a.jsx)(e.p,{children:"This pyramid has following slide down:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{children:" *3\n *7 4\n 2 *4 6\n8 5 *9 3\n"})}),"\n",(0,a.jsxs)(e.p,{children:["And its value is ",(0,a.jsx)(e.code,{children:"23"}),"."]}),"\n",(0,a.jsxs)(e.p,{children:["We can also have a look at a ",(0,a.jsx)(e.em,{children:"bigger"})," example:"]}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{children:" 75\n 95 64\n 17 47 82\n 18 35 87 10\n 20 4 82 47 65\n 19 1 23 3 34\n 88 2 77 73 7 63 67\n 99 65 4 28 6 16 70 92\n 41 41 26 56 83 40 80 70 33\n 41 48 72 33 47 32 37 16 94 29\n 53 71 44 65 25 43 91 52 97 51 14\n 70 11 33 28 77 73 17 78 39 68 17 57\n 91 71 52 38 17 14 91 43 58 50 27 29 48\n 63 66 4 68 89 53 67 30 73 16 69 87 40 31\n 4 62 98 27 23 9 70 98 73 93 38 53 60 4 23\n"})}),"\n",(0,a.jsxs)(e.p,{children:["Slide down in this case is equal to ",(0,a.jsx)(e.code,{children:"1074"}),"."]}),"\n",(0,a.jsx)(e.h2,{id:"solving-the-problem",children:"Solving the problem"}),"\n",(0,a.jsx)(e.admonition,{type:"caution",children:(0,a.jsxs)(e.p,{children:["I will describe the following ways you can approach this problem and implement\nthem in ",(0,a.jsx)(e.em,{children:"Java"}),(0,a.jsx)(e.sup,{children:(0,a.jsx)(e.a,{href:"#user-content-fn-1",id:"user-content-fnref-1","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"1"})}),"."]})}),"\n",(0,a.jsxs)(e.p,{children:["For all of the following solutions I will be using basic ",(0,a.jsx)(e.code,{children:"main"})," function that\nwill output ",(0,a.jsx)(e.code,{children:"true"}),"/",(0,a.jsx)(e.code,{children:"false"})," based on the expected output of our algorithm. Any\nother differences will lie only in the solutions of the problem. You can see the\n",(0,a.jsx)(e.code,{children:"main"})," here:"]}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:'public static void main(String[] args) {\n System.out.print("Test #1: ");\n System.out.println(longestSlideDown(new int[][] {\n { 3 },\n { 7, 4 },\n { 2, 4, 6 },\n { 8, 5, 9, 3 }\n }) == 23 ? "passed" : "failed");\n\n System.out.print("Test #2: ");\n System.out.println(longestSlideDown(new int[][] {\n { 75 },\n { 95, 64 },\n { 17, 47, 82 },\n { 18, 35, 87, 10 },\n { 20, 4, 82, 47, 65 },\n { 19, 1, 23, 75, 3, 34 },\n { 88, 2, 77, 73, 7, 63, 67 },\n { 99, 65, 4, 28, 6, 16, 70, 92 },\n { 41, 41, 26, 56, 83, 40, 80, 70, 33 },\n { 41, 48, 72, 33, 47, 32, 37, 16, 94, 29 },\n { 53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14 },\n { 70, 11, 33, 28, 77, 73, 17, 78, 39, 68, 17, 57 },\n { 91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27, 29, 48 },\n { 63, 66, 4, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31 },\n { 4, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 4, 23 },\n }) == 1074 ? "passed" : "failed");\n}\n'})}),"\n",(0,a.jsx)(e.h2,{id:"na\xefve-solution",children:"Na\xefve solution"}),"\n",(0,a.jsx)(e.p,{children:"Our na\xefve solution consists of trying out all the possible slides and finding\nthe one with maximum sum."}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"public static int longestSlideDown(int[][] pyramid, int row, int col) {\n if (row >= pyramid.length || col < 0 || col >= pyramid[row].length) {\n // BASE: We have gotten out of bounds, there's no reasonable value to\n // return, so we just return the \u2039MIN_VALUE\u203a to ensure that it cannot\n // be maximum.\n return Integer.MIN_VALUE;\n }\n\n if (row == pyramid.length - 1) {\n // BASE: Bottom of the pyramid, we just return the value, there's\n // nowhere to slide anymore.\n return pyramid[row][col];\n }\n\n // Otherwise we account for the current position and return maximum of the\n // available \u201cslides\u201d.\n return pyramid[row][col] + Math.max(\n longestSlideDown(pyramid, row + 1, col),\n longestSlideDown(pyramid, row + 1, col + 1));\n}\n\npublic static int longestSlideDown(int[][] pyramid) {\n // We start the slide in the top cell of the pyramid.\n return longestSlideDown(pyramid, 0, 0);\n}\n"})}),"\n",(0,a.jsx)(e.p,{children:"As you can see, we have 2 overloads:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"int longestSlideDown(int[][] pyramid);\nint longestSlideDown(int[][] pyramid, int row, int col);\n"})}),"\n",(0,a.jsxs)(e.p,{children:["First one is used as a ",(0,a.jsx)(e.em,{children:"public interface"})," to the solution, you just pass in the\npyramid itself. Second one is the recursive \u201calgorithm\u201d that finds the slide\ndown."]}),"\n",(0,a.jsxs)(e.p,{children:["It is a relatively simple solution\u2026 There's nothing to do at the bottom of the\npyramid, so we just return the value in the ",(0,a.jsx)(e.em,{children:"cell"}),". Otherwise we add it and try\nto slide down the available cells below the current row."]}),"\n",(0,a.jsx)(e.h3,{id:"time-complexity",children:"Time complexity"}),"\n",(0,a.jsx)(e.p,{children:"If you get the source code and run it yourself, it runs rather fine\u2026 I hope you\nare wondering about the time complexity of the proposed solution and, since it\nreally is a na\xefve solution, the time complexity is pretty bad. Let's find the\nworst case scenario."}),"\n",(0,a.jsx)(e.p,{children:"Let's start with the first overload:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"public static int longestSlideDown(int[][] pyramid) {\n return longestSlideDown(pyramid, 0, 0);\n}\n"})}),"\n",(0,a.jsxs)(e.p,{children:["There's not much to do here, so we can safely say that the time complexity of\nthis function is bounded by ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"T"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"T(n)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]}),", where ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mrow,{children:(0,a.jsx)(e.mi,{children:"T"})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"T"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"})]})})]})," is our second overload. This\ndoesn't tell us anything, so let's move on to the second overload where we are\ngoing to define the ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"T"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"T(n)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]})," function."]}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"public static int longestSlideDown(int[][] pyramid, int row, int col) {\n if (row >= pyramid.length || col < 0 || col >= pyramid[row].length) {\n // BASE: We have gotten out of bounds, there's no reasonable value to\n // return, so we just return the \u2039MIN_VALUE\u203a to ensure that it cannot\n // be maximum.\n return Integer.MIN_VALUE;\n }\n\n if (row == pyramid.length - 1) {\n // BASE: Bottom of the pyramid, we just return the value, there's\n // nowhere to slide anymore.\n return pyramid[row][col];\n }\n\n // Otherwise we account for the current position and return maximum of the\n // available \u201cslides\u201d.\n return pyramid[row][col] + Math.max(\n longestSlideDown(pyramid, row + 1, col),\n longestSlideDown(pyramid, row + 1, col + 1));\n}\n"})}),"\n",(0,a.jsxs)(e.p,{children:["Fun fact is that the whole \u201calgorithm\u201d consists of just 2 ",(0,a.jsx)(e.code,{children:"return"})," statements\nand nothing else. Let's dissect them!"]}),"\n",(0,a.jsxs)(e.p,{children:["First ",(0,a.jsx)(e.code,{children:"return"})," statement is the base case, so it has a constant time complexity."]}),"\n",(0,a.jsxs)(e.p,{children:["Second one a bit tricky. We add two numbers together, which we'll consider as\nconstant, but for the right part of the expression we take maximum from the left\nand right paths. OK\u2026 So what happens? We evaluate the ",(0,a.jsx)(e.code,{children:"longestSlideDown"})," while\nchoosing the under and right both. They are separate computations though, so we\nare branching from each call of ",(0,a.jsx)(e.code,{children:"longestSlideDown"}),", unless it's a base case."]}),"\n",(0,a.jsx)(e.p,{children:"What does that mean for us then? We basically get"}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"T"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"y"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mo,{fence:"true",children:"{"}),(0,a.jsxs)(e.mtable,{rowspacing:"0.36em",columnalign:"left left",columnspacing:"1em",children:[(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,a.jsx)(e.mn,{children:"1"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mtext,{children:",\xa0if\xa0"}),(0,a.jsx)(e.mi,{children:"y"}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"})]})})})]}),(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mn,{children:"1"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"T"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"y"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mn,{children:"1"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,a.jsx)(e.mtext,{children:",\xa0otherwise"})})})]})]})]})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"T(y) =\n\\begin{cases}\n1 & \\text{, if } y = rows \\\\\n1 + 2 \\cdot T(y + 1) & \\text{, otherwise}\n\\end{cases}"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"y"}),(0,a.jsx)(e.span,{className:"mclose",children:")"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"3em",verticalAlign:"-1.25em"}}),(0,a.jsxs)(e.span,{className:"minner",children:[(0,a.jsx)(e.span,{className:"mopen delimcenter",style:{top:"0em"},children:(0,a.jsx)(e.span,{className:"delimsizing size4",children:"{"})}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsxs)(e.span,{className:"mtable",children:[(0,a.jsx)(e.span,{className:"col-align-l",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.69em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.69em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.008em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord",children:"1"})})]}),(0,a.jsxs)(e.span,{style:{top:"-2.25em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.008em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord",children:"1"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"y"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord",children:"1"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.19em"},children:(0,a.jsx)(e.span,{})})})]})}),(0,a.jsx)(e.span,{className:"arraycolsep",style:{width:"1em"}}),(0,a.jsx)(e.span,{className:"col-align-l",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.69em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.69em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.008em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord text",children:(0,a.jsx)(e.span,{className:"mord",children:",\xa0if\xa0"})}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"y"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})]})]}),(0,a.jsxs)(e.span,{style:{top:"-2.25em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.008em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord text",children:(0,a.jsx)(e.span,{className:"mord",children:",\xa0otherwise"})})})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.19em"},children:(0,a.jsx)(e.span,{})})})]})})]})}),(0,a.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]})]})}),"\n",(0,a.jsx)(e.p,{children:"That looks rather easy to compute, isn't it? If you sum it up, you'll get:"}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"T"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"}),(0,a.jsx)(e.mo,{children:"\u2208"}),(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsxs)(e.msup,{children:[(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"})]})]}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"T(rows) \\in \\mathcal{O}(2^{rows})"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mclose",children:")"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"\u2208"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"msupsub",children:(0,a.jsx)(e.span,{className:"vlist-t",children:(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.7144em"},children:(0,a.jsxs)(e.span,{style:{top:"-3.113em",marginRight:"0.05em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsxs)(e.span,{className:"mord mtight",children:[(0,a.jsx)(e.span,{className:"mord mathnormal mtight",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal mtight",children:"s"})]})})]})})})})})]}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})]})]})}),"\n",(0,a.jsx)(e.p,{children:"If you wonder why, I'll try to describe it intuitively:"}),"\n",(0,a.jsxs)(e.ol,{children:["\n",(0,a.jsxs)(e.li,{children:["In each call to ",(0,a.jsx)(e.code,{children:"longestSlideDown"})," we do some work in constant time,\nregardless of being in the base case. Those are the ",(0,a.jsx)(e.code,{children:"1"}),"s in both cases."]}),"\n",(0,a.jsxs)(e.li,{children:["If we are not in the base case, we move one row down ",(0,a.jsx)(e.strong,{children:"twice"}),". That's how we\nobtained ",(0,a.jsx)(e.code,{children:"2 *"})," and ",(0,a.jsx)(e.code,{children:"y + 1"})," in the ",(0,a.jsx)(e.em,{children:"otherwise"})," case."]}),"\n",(0,a.jsxs)(e.li,{children:["We move row-by-row, so we move down ",(0,a.jsx)(e.code,{children:"y"}),"-times and each call splits to two\nsubtrees."]}),"\n",(0,a.jsxs)(e.li,{children:["Overall, if we were to represent the calls as a tree, we would get a full\nbinary tree of height ",(0,a.jsx)(e.code,{children:"y"}),", in each node we do some work in constant time,\ntherefore we can just sum the ones."]}),"\n"]}),"\n",(0,a.jsx)(e.admonition,{type:"warning",children:(0,a.jsx)(e.p,{children:"It would've been more complicated to get an exact result. In the equation above\nwe are assuming that the width of the pyramid is bound by the height."})}),"\n",(0,a.jsxs)(e.p,{children:["Hopefully we can agree that this is not the best we can do. ","\ud83d\ude09"]}),"\n",(0,a.jsx)(e.h2,{id:"greedy-solution",children:"Greedy solution"}),"\n",(0,a.jsxs)(e.p,{children:["We will try to optimize it a bit. Let's start with a relatively simple ",(0,a.jsx)(e.em,{children:"greedy"}),"\napproach."]}),"\n",(0,a.jsx)(e.admonition,{title:"Greedy algorithms",type:"info",children:(0,a.jsxs)(e.p,{children:[(0,a.jsx)(e.em,{children:"Greedy algorithms"})," can be described as algorithms that decide the action on the\noptimal option at the moment."]})}),"\n",(0,a.jsx)(e.p,{children:"We can try to adjust the na\xefve solution. The most problematic part are the\nrecursive calls. Let's apply the greedy approach there:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"public static int longestSlideDown(int[][] pyramid, int row, int col) {\n if (row == pyramid.length - 1) {\n // BASE: We're at the bottom\n return pyramid[row][col];\n }\n\n if (col + 1 >= pyramid[row + 1].length\n || pyramid[row + 1][col] > pyramid[row + 1][col + 1]) {\n // If we cannot go right or it's not feasible, we continue to the left.\n return pyramid[row][col] + longestSlideDown(pyramid, row + 1, col);\n }\n\n // Otherwise we just move to the right.\n return pyramid[row][col] + longestSlideDown(pyramid, row + 1, col + 1);\n}\n"})}),"\n",(0,a.jsxs)(e.p,{children:["OK, if we cannot go right ",(0,a.jsx)(e.strong,{children:"or"})," the right path adds smaller value to the sum,\nwe simply go left."]}),"\n",(0,a.jsx)(e.h3,{id:"time-complexity-1",children:"Time complexity"}),"\n",(0,a.jsxs)(e.p,{children:["We have switched from ",(0,a.jsx)(e.em,{children:"adding the maximum"})," to ",(0,a.jsx)(e.em,{children:"following the \u201cbigger\u201d path"}),", so\nwe improved the time complexity tremendously. We just go down the pyramid all\nthe way to the bottom. Therefore we are getting:"]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(rows)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]})}),"\n",(0,a.jsx)(e.p,{children:"We have managed to convert our exponential solution into a linear one."}),"\n",(0,a.jsx)(e.h3,{id:"running-the-tests",children:"Running the tests"}),"\n",(0,a.jsx)(e.p,{children:"However, if we run the tests, we notice that the second test failed:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{children:"Test #1: passed\nTest #2: failed\n"})}),"\n",(0,a.jsxs)(e.p,{children:["What's going on? Well, we have improved the time complexity, but greedy\nalgorithms are not the ideal solution to ",(0,a.jsx)(e.strong,{children:"all"})," problems. In this case there\nmay be a solution that is bigger than the one found using the greedy algorithm."]}),"\n",(0,a.jsx)(e.p,{children:"Imagine the following pyramid:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{children:" 1\n 2 3\n 5 6 7\n 8 9 10 11\n99 13 14 15 16\n"})}),"\n",(0,a.jsx)(e.p,{children:"We start at the top:"}),"\n",(0,a.jsxs)(e.ol,{children:["\n",(0,a.jsxs)(e.li,{children:["Current cell: ",(0,a.jsx)(e.code,{children:"1"}),", we can choose from ",(0,a.jsx)(e.code,{children:"2"})," and ",(0,a.jsx)(e.code,{children:"3"}),", ",(0,a.jsx)(e.code,{children:"3"})," looks better, so we\nchoose it."]}),"\n",(0,a.jsxs)(e.li,{children:["Current cell: ",(0,a.jsx)(e.code,{children:"3"}),", we can choose from ",(0,a.jsx)(e.code,{children:"6"})," and ",(0,a.jsx)(e.code,{children:"7"}),", ",(0,a.jsx)(e.code,{children:"7"})," looks better, so we\nchoose it."]}),"\n",(0,a.jsxs)(e.li,{children:["Current cell: ",(0,a.jsx)(e.code,{children:"7"}),", we can choose from ",(0,a.jsx)(e.code,{children:"10"})," and ",(0,a.jsx)(e.code,{children:"11"}),", ",(0,a.jsx)(e.code,{children:"11"})," looks better, so we\nchoose it."]}),"\n",(0,a.jsxs)(e.li,{children:["Current cell: ",(0,a.jsx)(e.code,{children:"11"}),", we can choose from ",(0,a.jsx)(e.code,{children:"15"})," and ",(0,a.jsx)(e.code,{children:"16"}),", ",(0,a.jsx)(e.code,{children:"16"})," looks better, so\nwe choose it."]}),"\n"]}),"\n",(0,a.jsxs)(e.p,{children:["Our final sum is: ",(0,a.jsx)(e.code,{children:"1 + 3 + 7 + 11 + 16 = 38"}),", but in the bottom left cell we\nhave a ",(0,a.jsx)(e.code,{children:"99"})," that is bigger than our whole sum."]}),"\n",(0,a.jsx)(e.admonition,{type:"tip",children:(0,a.jsx)(e.p,{children:"Dijkstra's algorithm is a greedy algorithm too, try to think why it is correct."})}),"\n",(0,a.jsx)(e.h2,{id:"top-down-dp",children:"Top-down DP"}),"\n",(0,a.jsxs)(e.p,{children:[(0,a.jsx)(e.em,{children:"Top-down dynamic programming"})," is probably the most common approach, since (at\nleast looks like) is the easiest to implement. The whole point is avoiding the\nunnecessary computations that we have already done."]}),"\n",(0,a.jsxs)(e.p,{children:["In our case, we can use our na\xefve solution and put a ",(0,a.jsx)(e.em,{children:"cache"})," on top of it that\nwill make sure, we don't do unnecessary calculations."]}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"// This \u201cstructure\u201d is required, since I have decided to use \u2039TreeMap\u203a which\n// requires the ordering on the keys. It represents one position in the pyramid.\nrecord Position(int row, int col) implements Comparable {\n public int compareTo(Position r) {\n if (row != r.row) {\n return Integer.valueOf(row).compareTo(r.row);\n }\n\n if (col != r.col) {\n return Integer.valueOf(col).compareTo(r.col);\n }\n\n return 0;\n }\n}\n\npublic static int longestSlideDown(\n int[][] pyramid,\n TreeMap cache,\n Position position) {\n int row = position.row;\n int col = position.col;\n\n if (row >= pyramid.length || col < 0 || col >= pyramid[row].length) {\n // BASE: out of bounds\n return Integer.MIN_VALUE;\n }\n\n if (row == pyramid.length - 1) {\n // BASE: bottom of the pyramid\n return pyramid[position.row][position.col];\n }\n\n if (!cache.containsKey(position)) {\n // We haven't computed the position yet, so we run the same \u201cformula\u201d as\n // in the na\xefve version \xbband\xab we put calculated slide into the cache.\n // Next time we want the slide down from given position, it will be just\n // retrieved from the cache.\n int slideDown = Math.max(\n longestSlideDown(pyramid, cache, new Position(row + 1, col)),\n longestSlideDown(pyramid, cache, new Position(row + 1, col + 1)));\n cache.put(position, pyramid[row][col] + slideDown);\n }\n\n return cache.get(position);\n}\n\npublic static int longestSlideDown(int[][] pyramid) {\n // At the beginning we need to create a cache and share it across the calls.\n TreeMap cache = new TreeMap<>();\n return longestSlideDown(pyramid, cache, new Position(0, 0));\n}\n"})}),"\n",(0,a.jsxs)(e.p,{children:["You have probably noticed that ",(0,a.jsx)(e.code,{children:"record Position"})," have appeared. Since we are\ncaching the already computed values, we need a \u201creasonable\u201d key. In this case we\nshare the cache only for one ",(0,a.jsx)(e.em,{children:"run"})," (i.e. pyramid) of the ",(0,a.jsx)(e.code,{children:"longestSlideDown"}),", so\nwe can cache just with the indices within the pyramid, i.e. the ",(0,a.jsx)(e.code,{children:"Position"}),"."]}),"\n",(0,a.jsx)(e.admonition,{title:"Record",type:"tip",children:(0,a.jsxs)(e.p,{children:[(0,a.jsx)(e.em,{children:"Record"})," is relatively new addition to the Java language. It is basically an\nimmutable structure with implicitly defined ",(0,a.jsx)(e.code,{children:".equals()"}),", ",(0,a.jsx)(e.code,{children:".hashCode()"}),",\n",(0,a.jsx)(e.code,{children:".toString()"})," and getters for the attributes."]})}),"\n",(0,a.jsxs)(e.p,{children:["Because of the choice of ",(0,a.jsx)(e.code,{children:"TreeMap"}),", we had to additionally define the ordering\non it."]}),"\n",(0,a.jsxs)(e.p,{children:["In the ",(0,a.jsx)(e.code,{children:"longestSlideDown"})," you can notice that the computation which used to be\nat the end of the na\xefve version above, is now wrapped in an ",(0,a.jsx)(e.code,{children:"if"})," statement that\nchecks for the presence of the position in the cache and computes the slide down\njust when it's needed."]}),"\n",(0,a.jsx)(e.h3,{id:"time-complexity-2",children:"Time complexity"}),"\n",(0,a.jsx)(e.p,{children:"If you think that evaluating time complexity for this approach is a bit more\ntricky, you are right. Keeping the cache in mind, it is not the easiest thing\nto do. However there are some observations that might help us figure this out:"}),"\n",(0,a.jsxs)(e.ol,{children:["\n",(0,a.jsx)(e.li,{children:"Slide down from each position is calculated only once."}),"\n",(0,a.jsx)(e.li,{children:"Once calculated, we use the result from the cache."}),"\n"]}),"\n",(0,a.jsxs)(e.p,{children:["Knowing this, we still cannot, at least easily, describe the time complexity of\nfinding the best slide down from a specific position, ",(0,a.jsx)(e.strong,{children:"but"})," we can bound it\nfrom above for the ",(0,a.jsx)(e.strong,{children:"whole"})," run from the top. Now the question is how we can do\nthat!"]}),"\n",(0,a.jsxs)(e.p,{children:["Overall we are doing the same things for almost",(0,a.jsx)(e.sup,{children:(0,a.jsx)(e.a,{href:"#user-content-fn-2",id:"user-content-fnref-2","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"2"})})," all of the positions within\nthe pyramid:"]}),"\n",(0,a.jsxs)(e.ol,{children:["\n",(0,a.jsxs)(e.li,{children:["\n",(0,a.jsx)(e.p,{children:"We calculate and store it (using the partial results stored in cache). This\nis done only once."}),"\n",(0,a.jsxs)(e.p,{children:["For each calculation we take 2 values from the cache and insert one value.\nBecause we have chosen ",(0,a.jsx)(e.code,{children:"TreeMap"}),", these 3 operations have logarithmic time\ncomplexity and therefore this step is equivalent to ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mn,{children:"3"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsxs)(e.msub,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"})]}),(0,a.jsx)(e.mn,{children:"2"})]}),(0,a.jsx)(e.mi,{children:"n"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"3 \\cdot \\log_2{n}"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.6444em"}}),(0,a.jsx)(e.span,{className:"mord",children:"3"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.9386em",verticalAlign:"-0.2441em"}}),(0,a.jsxs)(e.span,{className:"mop",children:[(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"msupsub",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.207em"},children:(0,a.jsxs)(e.span,{style:{top:"-2.4559em",marginRight:"0.05em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsx)(e.span,{className:"mord mtight",children:"2"})})]})}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.2441em"},children:(0,a.jsx)(e.span,{})})})]})})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]})]}),"."]}),"\n",(0,a.jsx)(e.p,{children:"However for the sake of simplicity, we are going to account only for the\ninsertion, the reason is rather simple, if we include the 2 retrievals here,\nit will be interleaved with the next step, therefore it is easier to keep the\nretrievals in the following point."}),"\n",(0,a.jsx)(e.admonition,{type:"caution",children:(0,a.jsx)(e.p,{children:"You might have noticed it's still not that easy, cause we're not having full\ncache right from the beginning, but the sum of those logarithms cannot be\nexpressed in a nice way, so taking the upper bound, i.e. expecting the cache\nto be full at all times, is the best option for nice and readable complexity\nof the whole approach."})}),"\n",(0,a.jsxs)(e.p,{children:["Our final upper bound of this work is therefore ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsxs)(e.msub,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"})]}),(0,a.jsx)(e.mn,{children:"2"})]}),(0,a.jsx)(e.mi,{children:"n"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\log_2{n}"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.9386em",verticalAlign:"-0.2441em"}}),(0,a.jsxs)(e.span,{className:"mop",children:[(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"msupsub",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.207em"},children:(0,a.jsxs)(e.span,{style:{top:"-2.4559em",marginRight:"0.05em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsx)(e.span,{className:"mord mtight",children:"2"})})]})}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.2441em"},children:(0,a.jsx)(e.span,{})})})]})})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})})]}),"."]}),"\n"]}),"\n",(0,a.jsxs)(e.li,{children:["\n",(0,a.jsxs)(e.p,{children:["We retrieve it from the cache. Same as in first point, but only twice, so we\nget ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsxs)(e.msub,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"})]}),(0,a.jsx)(e.mn,{children:"2"})]}),(0,a.jsx)(e.mi,{children:"n"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"2 \\cdot \\log_2{n}"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.6444em"}}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.9386em",verticalAlign:"-0.2441em"}}),(0,a.jsxs)(e.span,{className:"mop",children:[(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"msupsub",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.207em"},children:(0,a.jsxs)(e.span,{style:{top:"-2.4559em",marginRight:"0.05em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsx)(e.span,{className:"mord mtight",children:"2"})})]})}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.2441em"},children:(0,a.jsx)(e.span,{})})})]})})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]})]}),"."]}),"\n",(0,a.jsx)(e.admonition,{type:"caution",children:(0,a.jsxs)(e.p,{children:["It's done twice because of the ",(0,a.jsx)(e.code,{children:".containsKey()"})," in the ",(0,a.jsx)(e.code,{children:"if"})," condition."]})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(e.p,{children:"Okay, we have evaluated work done for each of the cells in the pyramid and now\nwe need to put it together."}),"\n",(0,a.jsx)(e.p,{children:"Let's split the time complexity of our solution into two operands:"}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(r + s)"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})]})]})}),"\n",(0,a.jsxs)(e.p,{children:[(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mrow,{children:(0,a.jsx)(e.mi,{children:"r"})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"r"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"})]})})]})," will represent the ",(0,a.jsx)(e.em,{children:"actual"})," calculation of the cells and ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mrow,{children:(0,a.jsx)(e.mi,{children:"s"})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"s"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})]})})]})," will represent\nthe additional retrievals on top of the calculation."]}),"\n",(0,a.jsxs)(e.p,{children:["We calculate the values only ",(0,a.jsx)(e.strong,{children:"once"}),", therefore we can safely agree on:"]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mtable,{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em",children:(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsx)(e.mi,{children:"r"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mrow,{}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"})]})})})]})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\begin{align*}\nr &= n \\cdot \\log{n} \\\\\n\\end{align*}"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1.5em",verticalAlign:"-0.5em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsxs)(e.span,{className:"mtable",children:[(0,a.jsx)(e.span,{className:"col-align-r",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsx)(e.span,{className:"vlist",style:{height:"1em"},children:(0,a.jsxs)(e.span,{style:{top:"-3.16em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"})})]})}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.5em"},children:(0,a.jsx)(e.span,{})})})]})}),(0,a.jsx)(e.span,{className:"col-align-l",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsx)(e.span,{className:"vlist",style:{height:"1em"},children:(0,a.jsxs)(e.span,{style:{top:"-3.16em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]})}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.5em"},children:(0,a.jsx)(e.span,{})})})]})})]})})]})})]})}),"\n",(0,a.jsxs)(e.p,{children:["What about the ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mrow,{children:(0,a.jsx)(e.mi,{children:"s"})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"s"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})]})})]})," though? Key observation here is the fact that we have 2\nlookups on the tree in each of them ",(0,a.jsx)(e.strong,{children:"and"})," we do it twice, cause each cell has\nat most 2 parents:"]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mtable,{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em",children:[(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsx)(e.mi,{children:"s"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mrow,{}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mo,{fence:"true",children:"("}),(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{fence:"true",children:")"})]})]})})})]}),(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsx)(e.mi,{children:"s"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mrow,{}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mn,{children:"4"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"})]})})})]})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\begin{align*}\ns &= n \\cdot 2 \\cdot \\left( 2 \\cdot \\log{n} \\right) \\\\\ns &= 4 \\cdot n \\cdot \\log{n}\n\\end{align*}"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"3em",verticalAlign:"-1.25em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsxs)(e.span,{className:"mtable",children:[(0,a.jsx)(e.span,{className:"col-align-r",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.75em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.91em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})})]}),(0,a.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.25em"},children:(0,a.jsx)(e.span,{})})})]})}),(0,a.jsx)(e.span,{className:"col-align-l",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.75em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.91em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"minner",children:[(0,a.jsx)(e.span,{className:"mopen delimcenter",style:{top:"0em"},children:"("}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})}),(0,a.jsx)(e.span,{className:"mclose delimcenter",style:{top:"0em"},children:")"})]})]})]}),(0,a.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord",children:"4"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.25em"},children:(0,a.jsx)(e.span,{})})})]})})]})})]})})]})}),"\n",(0,a.jsxs)(e.admonition,{type:"tip",children:[(0,a.jsxs)(e.p,{children:["You might've noticed that lookups actually take more time than the construction\nof the results. This is not entirely true, since we have included the\n",(0,a.jsx)(e.code,{children:".containsKey()"})," and ",(0,a.jsx)(e.code,{children:".get()"})," from the ",(0,a.jsx)(e.code,{children:"return"})," statement in the second part."]}),(0,a.jsx)(e.p,{children:"If we were to represent this more precisely, we could've gone with:"}),(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mtable,{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em",children:[(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsx)(e.mi,{children:"r"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mrow,{}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mn,{children:"3"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"})]})})})]}),(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsx)(e.mi,{children:"s"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mrow,{}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"})]})})})]})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\begin{align*}\nr &= 3 \\cdot n \\cdot \\log{n} \\\\\ns &= 2 \\cdot n \\cdot \\log{n}\n\\end{align*}"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"3em",verticalAlign:"-1.25em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsxs)(e.span,{className:"mtable",children:[(0,a.jsx)(e.span,{className:"col-align-r",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.75em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.91em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"})})]}),(0,a.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.25em"},children:(0,a.jsx)(e.span,{})})})]})}),(0,a.jsx)(e.span,{className:"col-align-l",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.75em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.91em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord",children:"3"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]}),(0,a.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.25em"},children:(0,a.jsx)(e.span,{})})})]})})]})})]})})]})}),(0,a.jsx)(e.p,{children:"On the other hand we are summing both numbers together, therefore in the end it\ndoesn't really matter."}),(0,a.jsxs)(e.p,{children:["(",(0,a.jsx)(e.em,{children:"Feel free to compare the sums of both \u201csplits\u201d."}),")"]})]}),"\n",(0,a.jsxs)(e.p,{children:["And so our final time complexity for the whole ",(0,a.jsx)(e.em,{children:"top-down dynamic programming"}),"\napproach is:"]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"}),(0,a.jsx)(e.mspace,{linebreak:"newline"}),(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mn,{children:"4"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"}),(0,a.jsx)(e.mspace,{linebreak:"newline"}),(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mn,{children:"5"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"}),(0,a.jsx)(e.mspace,{linebreak:"newline"}),(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(r + s) \\\\\n\\mathcal{O}(n \\cdot \\log{n} + 4 \\cdot n \\cdot \\log{n}) \\\\\n\\mathcal{O}(5 \\cdot n \\cdot \\log{n}) \\\\\n\\mathcal{O}(n \\cdot \\log{n})"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]}),(0,a.jsx)(e.span,{className:"mspace newline"}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.8889em",verticalAlign:"-0.1944em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.6444em"}}),(0,a.jsx)(e.span,{className:"mord",children:"4"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4445em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]}),(0,a.jsx)(e.span,{className:"mspace newline"}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord",children:"5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4445em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]}),(0,a.jsx)(e.span,{className:"mspace newline"}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})]})]})}),"\n",(0,a.jsxs)(e.p,{children:["As you can see, this is worse than our ",(0,a.jsx)(e.em,{children:"greedy"})," solution that was incorrect, but\nit's better than the ",(0,a.jsx)(e.em,{children:"na\xefve"})," one."]}),"\n",(0,a.jsx)(e.h3,{id:"memory-complexity",children:"Memory complexity"}),"\n",(0,a.jsxs)(e.p,{children:["With this approach we need to talk about the memory complexity too, because we\nhave introduced cache. If you think that the memory complexity is linear to the\ninput, you are right. We start at the top and try to find each and every slide\ndown. At the end we get the final result for ",(0,a.jsx)(e.code,{children:"new Position(0, 0)"}),", so we need to\ncompute everything below."]}),"\n",(0,a.jsx)(e.p,{children:"That's how we obtain:"}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(n)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]})}),"\n",(0,a.jsxs)(e.p,{children:[(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mrow,{children:(0,a.jsx)(e.mi,{children:"n"})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"n"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})]})})]})," represents the total amount of cells in the pyramid, i.e."]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsxs)(e.munderover,{children:[(0,a.jsx)(e.mo,{children:"\u2211"}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"y"}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mn,{children:"0"})]}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"p"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"y"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"r"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"a"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"m"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"i"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"d"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"."}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"l"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"e"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"n"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"g"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"t"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"h"})]}),(0,a.jsx)(e.mo,{children:"\u2212"}),(0,a.jsx)(e.mn,{children:"1"})]})]}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"p"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"y"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"r"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"a"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"m"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"i"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"d"})]}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mo,{fence:"true",children:"["}),(0,a.jsx)(e.mi,{children:"y"}),(0,a.jsx)(e.mo,{fence:"true",children:"]"})]}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"."}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"l"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"e"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"n"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"g"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"t"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"h"})]})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\sum_{y=0}^{\\mathtt{pyramid.length} - 1} \\mathtt{pyramid}\\left[y\\right]\\mathtt{.length}"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"3.2709em",verticalAlign:"-1.4032em"}}),(0,a.jsx)(e.span,{className:"mop op-limits",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.8677em"},children:[(0,a.jsxs)(e.span,{style:{top:"-1.8829em",marginLeft:"0em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsxs)(e.span,{className:"mord mtight",children:[(0,a.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.03588em"},children:"y"}),(0,a.jsx)(e.span,{className:"mrel mtight",children:"="}),(0,a.jsx)(e.span,{className:"mord mtight",children:"0"})]})})]}),(0,a.jsxs)(e.span,{style:{top:"-3.05em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,a.jsx)(e.span,{children:(0,a.jsx)(e.span,{className:"mop op-symbol large-op",children:"\u2211"})})]}),(0,a.jsxs)(e.span,{style:{top:"-4.3666em",marginLeft:"0em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsxs)(e.span,{className:"mord mtight",children:[(0,a.jsx)(e.span,{className:"mord mtight",children:(0,a.jsx)(e.span,{className:"mord mathtt mtight",children:"pyramid.length"})}),(0,a.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,a.jsx)(e.span,{className:"mord mtight",children:"1"})]})})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.4032em"},children:(0,a.jsx)(e.span,{})})})]})}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathtt",children:"pyramid"})}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsxs)(e.span,{className:"minner",children:[(0,a.jsx)(e.span,{className:"mopen delimcenter",style:{top:"0em"},children:"["}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"y"}),(0,a.jsx)(e.span,{className:"mclose delimcenter",style:{top:"0em"},children:"]"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathtt",children:".length"})})]})})]})}),"\n",(0,a.jsx)(e.admonition,{type:"caution",children:(0,a.jsxs)(e.p,{children:["If you're wondering whether it's correct because of the second ",(0,a.jsx)(e.code,{children:"if"})," in our\nfunction, your guess is right. However we are expressing the complexity in the\nBachmann-Landau notation, so we care about the ",(0,a.jsx)(e.strong,{children:"upper bound"}),", not the exact\nnumber."]})}),"\n",(0,a.jsxs)(e.admonition,{title:"Can this be optimized?",type:"tip",children:[(0,a.jsx)(e.p,{children:"Yes, it can! Try to think about a way, how can you minimize the memory\ncomplexity of this approach. I'll give you a hint:"}),(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(rows)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]})})]}),"\n",(0,a.jsx)(e.h2,{id:"bottom-up-dp",children:"Bottom-up DP"}),"\n",(0,a.jsxs)(e.p,{children:["If you try to think in depth about the top-down DP solution, you might notice\nthat the ",(0,a.jsx)(e.em,{children:"core"})," of it stands on caching the calculations that have been already\ndone on the lower \u201clevels\u201d of the pyramid. Our bottom-up implementation will be\nusing this fact!"]}),"\n",(0,a.jsxs)(e.admonition,{type:"tip",children:[(0,a.jsxs)(e.p,{children:["As I have said in the ",(0,a.jsx)(e.em,{children:"top-down DP"})," section, it is the easiest way to implement\nDP (unless the cached function has complicated parameters, in that case it might\nget messy)."]}),(0,a.jsx)(e.p,{children:"Bottom-up dynamic programming can be more effective, but may be more complicated\nto implement right from the beginning."})]}),"\n",(0,a.jsx)(e.p,{children:"Let's see how we can implement it:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"public static int longestSlideDown(int[][] pyramid) {\n // In the beginning we declare new array. At this point it is easier to just\n // work with the one dimension, i.e. just allocating the space for the rows.\n int[][] slideDowns = new int[pyramid.length][];\n\n // Bottom row gets just copied, there's nothing else to do\u2026 It's the base\n // case.\n slideDowns[pyramid.length - 1] = Arrays.copyOf(pyramid[pyramid.length - 1],\n pyramid[pyramid.length - 1].length);\n\n // Then we need to propagate the found slide downs for each of the levels\n // above.\n for (int y = pyramid.length - 2; y >= 0; --y) {\n // We start by copying the values lying in the row we're processing.\n // They get included in the final sum and we need to allocate the space\n // for the precalculated slide downs anyways.\n int[] row = Arrays.copyOf(pyramid[y], pyramid[y].length);\n\n // At this we just need to \u201cfetch\u201d the partial results from \u201cneighbours\u201d\n for (int x = 0; x < row.length; ++x) {\n // We look under our position, since we expect the rows to get\n // shorter, we can safely assume such position exists.\n int under = slideDowns[y + 1][x];\n\n // Then we have a look to the right, such position doesn't have to\n // exist, e.g. on the right edge, so we validate the index, and if\n // it doesn't exist, we just assign minimum of the \u2039int\u203a which makes\n // sure that it doesn't get picked in the \u2039Math.max()\u203a call.\n int toRight = x + 1 < slideDowns[y + 1].length\n ? slideDowns[y + 1][x + 1]\n : Integer.MIN_VALUE;\n\n // Finally we add the best choice at this point.\n row[x] += Math.max(under, toRight);\n }\n\n // And save the row we've just calculated partial results for to the\n // \u201ctable\u201d.\n slideDowns[y] = row;\n }\n\n // At the end we can find our seeked slide down at the top cell.\n return slideDowns[0][0];\n}\n"})}),"\n",(0,a.jsx)(e.p,{children:"I've tried to explain the code as much as possible within the comments, since it\nmight be more beneficial to see right next to the \u201coffending\u201d lines."}),"\n",(0,a.jsxs)(e.p,{children:["As you can see, in this approach we go from the other side",(0,a.jsx)(e.sup,{children:(0,a.jsx)(e.a,{href:"#user-content-fn-3",id:"user-content-fnref-3","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"3"})}),", the bottom of\nthe pyramid and propagate the partial results up."]}),"\n",(0,a.jsxs)(e.admonition,{type:"info",children:[(0,a.jsxs)(e.mdxAdmonitionTitle,{children:["How is this different from the ",(0,a.jsx)(e.em,{children:"greedy"})," solution???"]}),(0,a.jsxs)(e.p,{children:["If you try to compare them, you might find a very noticable difference. The\ngreedy approach is going from the top to the bottom without ",(0,a.jsx)(e.strong,{children:"any"})," knowledge of\nwhat's going on below. On the other hand, bottom-up DP is going from the bottom\n(",(0,a.jsx)(e.em,{children:"DUH\u2026"}),") and ",(0,a.jsx)(e.strong,{children:"propagates"})," the partial results to the top. The propagation is\nwhat makes sure that at the top I don't choose the best ",(0,a.jsx)(e.strong,{children:"local"})," choice, but\nthe best ",(0,a.jsx)(e.strong,{children:"overall"})," result I can achieve."]})]}),"\n",(0,a.jsx)(e.h3,{id:"time-complexity-3",children:"Time complexity"}),"\n",(0,a.jsx)(e.p,{children:"Time complexity of this solution is rather simple. We allocate an array for the\nrows and then for each row, we copy it and adjust the partial results. Doing\nthis we get:"}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(rows + 2n)"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})]})]})}),"\n",(0,a.jsx)(e.p,{children:"Of course, this is an upper bound, since we iterate through the bottom row only\nonce."}),"\n",(0,a.jsx)(e.h3,{id:"memory-complexity-1",children:"Memory complexity"}),"\n",(0,a.jsxs)(e.p,{children:["We're allocating an array for the pyramid ",(0,a.jsx)(e.strong,{children:"again"})," for our partial results, so\nwe get:"]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(n)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]})}),"\n",(0,a.jsxs)(e.admonition,{type:"tip",children:[(0,a.jsx)(e.p,{children:"If we were writing this in C++ or Rust, we could've avoided that, but not\nreally."}),(0,a.jsxs)(e.p,{children:["C++ would allow us to ",(0,a.jsx)(e.strong,{children:"copy"})," the pyramid rightaway into the parameter, so we\nwould be able to directly change it. However it's still a copy, even though we\ndon't need to allocate anything ourselves. It's just implicitly done for us."]}),(0,a.jsxs)(e.p,{children:["Rust is more funny in this case. If the pyramids weren't used after the call of\n",(0,a.jsx)(e.code,{children:"longest_slide_down"}),", it would simply ",(0,a.jsx)(e.strong,{children:"move"})," them into the functions. If they\nwere used afterwards, the compiler would force you to either borrow it, or\n",(0,a.jsx)(e.em,{children:"clone-and-move"})," for the function."]}),(0,a.jsx)(e.hr,{}),(0,a.jsxs)(e.p,{children:["Since we're doing it in Java, we get a reference to the ",(0,a.jsx)(e.em,{children:"original"})," array and we\ncan't do whatever we want with it."]})]}),"\n",(0,a.jsx)(e.h2,{id:"summary",children:"Summary"}),"\n",(0,a.jsxs)(e.p,{children:["And we've finally reached the end. We have seen 4 different \u201csolutions\u201d",(0,a.jsx)(e.sup,{children:(0,a.jsx)(e.a,{href:"#user-content-fn-4",id:"user-content-fnref-4","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"4"})})," of\nthe same problem using different approaches. Different approaches follow the\norder in which you might come up with them, each approach influences its\nsuccessor and represents the way we can enhance the existing implementation."]}),"\n",(0,a.jsx)(e.hr,{}),"\n",(0,a.jsx)(e.admonition,{title:"source",type:"info",children:(0,a.jsxs)(e.p,{children:["You can find source code referenced in the text\n",(0,a.jsx)(e.a,{href:"pathname:///files/algorithms/recursion/pyramid-slide-down.tar.gz",children:"here"}),"."]})}),"\n",(0,a.jsxs)(e.section,{"data-footnotes":!0,className:"footnotes",children:[(0,a.jsx)(e.h2,{className:"sr-only",id:"footnote-label",children:"Footnotes"}),"\n",(0,a.jsxs)(e.ol,{children:["\n",(0,a.jsxs)(e.li,{id:"user-content-fn-1",children:["\n",(0,a.jsxs)(e.p,{children:["cause why not, right!? ",(0,a.jsx)(e.a,{href:"#user-content-fnref-1","data-footnote-backref":"","aria-label":"Back to reference 1",className:"data-footnote-backref",children:"\u21a9"})]}),"\n"]}),"\n",(0,a.jsxs)(e.li,{id:"user-content-fn-2",children:["\n",(0,a.jsxs)(e.p,{children:["except the bottom row ",(0,a.jsx)(e.a,{href:"#user-content-fnref-2","data-footnote-backref":"","aria-label":"Back to reference 2",className:"data-footnote-backref",children:"\u21a9"})]}),"\n"]}),"\n",(0,a.jsxs)(e.li,{id:"user-content-fn-3",children:["\n",(0,a.jsxs)(e.p,{children:["definitely not an RHCP reference ","\ud83d\ude09 ",(0,a.jsx)(e.a,{href:"#user-content-fnref-3","data-footnote-backref":"","aria-label":"Back to reference 3",className:"data-footnote-backref",children:"\u21a9"})]}),"\n"]}),"\n",(0,a.jsxs)(e.li,{id:"user-content-fn-4",children:["\n",(0,a.jsxs)(e.p,{children:["one was not correct, thus the quotes ",(0,a.jsx)(e.a,{href:"#user-content-fnref-4","data-footnote-backref":"","aria-label":"Back to reference 4",className:"data-footnote-backref",children:"\u21a9"})]}),"\n"]}),"\n"]}),"\n"]})]})}function o(s={}){const{wrapper:e}={...(0,i.a)(),...s.components};return e?(0,a.jsx)(e,{...s,children:(0,a.jsx)(h,{...s})}):h(s)}},1151:(s,e,n)=>{n.d(e,{Z:()=>r,a:()=>t});var a=n(7294);const i={},l=a.createContext(i);function t(s){const e=a.useContext(l);return a.useMemo((function(){return"function"==typeof s?s(e):{...e,...s}}),[e,s])}function r(s){let e;return e=s.disableParentContext?"function"==typeof s.components?s.components(i):s.components||i:t(s.components),a.createElement(l.Provider,{value:e},s.children)}}}]);