Skip to content

Commit da705a1

Browse files
1 parent 9392a34 commit da705a1

File tree

7 files changed

+188
-186
lines changed

7 files changed

+188
-186
lines changed

main/dynamic_programming/intro-to-dp.html

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2204,7 +2204,7 @@
22042204
<li class="md-nav__item">
22052205
<a href="#dp-contests" class="md-nav__link">
22062206
<span class="md-ellipsis">
2207-
Dp Contests
2207+
DP Contests
22082208
</span>
22092209
</a>
22102210

@@ -6516,6 +6516,12 @@
65166516

65176517

65186518

6519+
6520+
6521+
6522+
6523+
6524+
65196525

65206526

65216527

@@ -6604,10 +6610,6 @@
66046610

66056611

66066612

6607-
6608-
6609-
6610-
66116613

66126614

66136615

@@ -6620,7 +6622,7 @@
66206622
<ul class="metadata page-metadata" data-bi-name="page info" lang="en-us" dir="ltr">
66216623

66226624
Last update:
6623-
<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">October 11, 2024</span>&emsp;
6625+
<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">October 24, 2024</span>&emsp;
66246626

66256627
<!-- Tags -->
66266628

@@ -6647,7 +6649,7 @@ <h1 id="introduction-to-dynamic-programming">Introduction to Dynamic Programming
66476649
<h2 id="speeding-up-fibonacci-with-dynamic-programming-memoization">Speeding up Fibonacci with Dynamic Programming (Memoization)<a class="headerlink" href="#speeding-up-fibonacci-with-dynamic-programming-memoization" title="Permanent link">&para;</a></h2>
66486650
<p>Our recursive function currently solves fibonacci in exponential time. This means that we can only handle small input values before the problem becomes too difficult. For instance, <span class="arithmatex">$f(29)$</span> results in <em>over 1 million</em> function calls!</p>
66496651
<p>To increase the speed, we recognize that the number of subproblems is only <span class="arithmatex">$O(n)$</span>. That is, in order to calculate <span class="arithmatex">$f(n)$</span> we only need to know <span class="arithmatex">$f(n-1),f(n-2), \dots ,f(0)$</span>. Therefore, instead of recalculating these subproblems, we solve them once and then save the result in a lookup table. Subsequent calls will use this lookup table and immediately return a result, thus eliminating exponential work! </p>
6650-
<p>Each recursive call will check against a lookup table to see if the value has been calculated. This is done in <span class="arithmatex">$O(1)$</span> time. If we have previously calcuated it, return the result, otherwise, we calculate the function normally. The overall runtime is <span class="arithmatex">$O(n)$</span>! This is an enormous improvement over our previous exponential time algorithm!</p>
6652+
<p>Each recursive call will check against a lookup table to see if the value has been calculated. This is done in <span class="arithmatex">$O(1)$</span> time. If we have previously calcuated it, return the result, otherwise, we calculate the function normally. The overall runtime is <span class="arithmatex">$O(n)$</span>. This is an enormous improvement over our previous exponential time algorithm!</p>
66516653
<div class="highlight"><pre><span></span><code><span class="k">const</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">MAXN</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">100</span><span class="p">;</span>
66526654
<span class="kt">bool</span><span class="w"> </span><span class="n">found</span><span class="p">[</span><span class="n">MAXN</span><span class="p">];</span>
66536655
<span class="kt">int</span><span class="w"> </span><span class="n">memo</span><span class="p">[</span><span class="n">MAXN</span><span class="p">];</span>
@@ -6662,7 +6664,7 @@ <h2 id="speeding-up-fibonacci-with-dynamic-programming-memoization">Speeding up
66626664
<span class="p">}</span>
66636665
</code></pre></div>
66646666
<p>With our new memoized recursive function, <span class="arithmatex">$f(29)$</span>, which used to result in <em>over 1 million calls</em>, now results in <em>only 57</em> calls, nearly <em>20,000 times</em> fewer function calls! Ironically, we are now limited by our data type. <span class="arithmatex">$f(46)$</span> is the last fibonacci number that can fit into a signed 32-bit integer.</p>
6665-
<p>Typically, we try to save states in arrays,if possible, since the lookup time is <span class="arithmatex">$O(1)$</span> with minimal overhead. However, more generically, we can save states anyway we like. Other examples include maps (binary search trees) or unordered_maps (hash tables).</p>
6667+
<p>Typically, we try to save states in arrays, if possible, since the lookup time is <span class="arithmatex">$O(1)$</span> with minimal overhead. However, more generically, we can save states any way we like. Other examples include binary search trees (<code>map</code> in C++) or hash tables (<code>unordered_map</code> in C++).</p>
66666668
<p>An example of this might be:</p>
66676669
<div class="highlight"><pre><span></span><code><span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">memo</span><span class="p">;</span>
66686670
<span class="kt">int</span><span class="w"> </span><span class="nf">f</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
@@ -6691,7 +6693,7 @@ <h2 id="speeding-up-fibonacci-with-dynamic-programming-memoization">Speeding up
66916693
<p>This approach is called top-down, as we can call the function with a query value and the calculation starts going from the top (queried value) down to the bottom (base cases of the recursion), and makes shortcuts via memoization on the way.</p>
66926694
<h2 id="bottom-up-dynamic-programming">Bottom-up Dynamic Programming<a class="headerlink" href="#bottom-up-dynamic-programming" title="Permanent link">&para;</a></h2>
66936695
<p>Until now you've only seen top-down dynamic programming with memoization. However, we can also solve problems with bottom-up dynamic programming.
6694-
Bottom up is exactly the opposite of top-down, you start at the bottom (base cases of the recursion), and extend it to more and more values.</p>
6696+
Bottom-up is exactly the opposite of top-down, you start at the bottom (base cases of the recursion), and extend it to more and more values.</p>
66956697
<p>To create a bottom-up approach for fibonacci numbers, we initilize the base cases in an array. Then, we simply use the recursive definition on array:</p>
66966698
<div class="highlight"><pre><span></span><code><span class="k">const</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">MAXN</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">100</span><span class="p">;</span>
66976699
<span class="kt">int</span><span class="w"> </span><span class="n">fib</span><span class="p">[</span><span class="n">MAXN</span><span class="p">];</span>
@@ -6707,7 +6709,7 @@ <h2 id="bottom-up-dynamic-programming">Bottom-up Dynamic Programming<a class="he
67076709
<p>Of course, as written, this is a bit silly for two reasons:
67086710
Firstly, we do repeated work if we call the function more than once.
67096711
Secondly, we only need to use the two previous values to calculate the current element. Therefore, we can reduce our memory from <span class="arithmatex">$O(n)$</span> to <span class="arithmatex">$O(1)$</span>. </p>
6710-
<p>An example of a bottom up dynamic programming solution for fibonacci which uses <span class="arithmatex">$O(1)$</span> might be:</p>
6712+
<p>An example of a bottom-up dynamic programming solution for fibonacci which uses <span class="arithmatex">$O(1)$</span> might be:</p>
67116713
<div class="highlight"><pre><span></span><code><span class="k">const</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">MAX_SAVE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">3</span><span class="p">;</span>
67126714
<span class="kt">int</span><span class="w"> </span><span class="n">fib</span><span class="p">[</span><span class="n">MAX_SAVE</span><span class="p">];</span>
67136715

@@ -6720,8 +6722,8 @@ <h2 id="bottom-up-dynamic-programming">Bottom-up Dynamic Programming<a class="he
67206722
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">fib</span><span class="p">[</span><span class="n">n</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="n">MAX_SAVE</span><span class="p">];</span>
67216723
<span class="p">}</span>
67226724
</code></pre></div>
6723-
<p>Note that we've changed the constant from <code>MAXN</code> TO <code>MAX_SAVE</code>. This is because the total number of elements we need to have access to is only 3. It no longer scales with the size of input and is, by definition, <span class="arithmatex">$O(1)$</span> memory. Additionally, we use a common trick (using the modulo operator) only maintaining the values we need.</p>
6724-
<p>That's it. That's the basics of dynamic programming: Don't repeat work you've done before.</p>
6725+
<p>Note that we've changed the constant from <code>MAXN</code> TO <code>MAX_SAVE</code>. This is because the total number of elements we need to access is only 3. It no longer scales with the size of input and is, by definition, <span class="arithmatex">$O(1)$</span> memory. Additionally, we use a common trick (using the modulo operator) only maintaining the values we need.</p>
6726+
<p>That's it. That's the basics of dynamic programming: Don't repeat the work you've done before.</p>
67256727
<p>One of the tricks to getting better at dynamic programming is to study some of the classic examples.</p>
67266728
<h2 id="classic-dynamic-programming-problems">Classic Dynamic Programming Problems<a class="headerlink" href="#classic-dynamic-programming-problems" title="Permanent link">&para;</a></h2>
67276729
<table>
@@ -6733,19 +6735,19 @@ <h2 id="classic-dynamic-programming-problems">Classic Dynamic Programming Proble
67336735
</thead>
67346736
<tbody>
67356737
<tr>
6736-
<td>0-1 knapsack</td>
6738+
<td>0-1 Knapsack</td>
67376739
<td>Given <span class="arithmatex">$W$</span>, <span class="arithmatex">$N$</span>, and <span class="arithmatex">$N$</span> items with weights <span class="arithmatex">$w_i$</span> and values <span class="arithmatex">$v_i$</span>, what is the maximum <span class="arithmatex">$\sum_{i=1}^{k} v_i$</span> for each subset of items of size <span class="arithmatex">$k$</span> (<span class="arithmatex">$1 \le k \le N$</span>) while ensuring <span class="arithmatex">$\sum_{i=1}^{k} w_i \le W$</span>?</td>
67386740
</tr>
67396741
<tr>
67406742
<td>Subset Sum</td>
67416743
<td>Given <span class="arithmatex">$N$</span> integers and <span class="arithmatex">$T$</span>, determine whether there exists a subset of the given set whose elements sum up to the <span class="arithmatex">$T$</span>.</td>
67426744
</tr>
67436745
<tr>
6744-
<td>Longest Increasing Subsequence</td>
6746+
<td>Longest Increasing Subsequence (LIS)</td>
67456747
<td>You are given an array containing <span class="arithmatex">$N$</span> integers. Your task is to determine the LIS in the array, i.e., a subsequence where every element is larger than the previous one.</td>
67466748
</tr>
67476749
<tr>
6748-
<td>Counting all possible paths in a matrix.</td>
6750+
<td>Counting Paths in a 2D Array</td>
67496751
<td>Given <span class="arithmatex">$N$</span> and <span class="arithmatex">$M$</span>, count all possible distinct paths from <span class="arithmatex">$(1,1)$</span> to <span class="arithmatex">$(N, M)$</span>, where each step is either from <span class="arithmatex">$(i,j)$</span> to <span class="arithmatex">$(i+1,j)$</span> or <span class="arithmatex">$(i,j+1)$</span>.</td>
67506752
</tr>
67516753
<tr>
@@ -6788,15 +6790,15 @@ <h2 id="practice-problems">Practice Problems<a class="headerlink" href="#practic
67886790
<li><a href="https://leetcode.com/problems/maximal-square/description/">LeetCode - 221. Maximal Square</a></li>
67896791
<li><a href="https://leetcode.com/problems/minimum-score-triangulation-of-polygon/description/">LeetCode - 1039. Minimum Score Triangulation of Polygon</a></li>
67906792
</ul>
6791-
<h2 id="dp-contests">Dp Contests<a class="headerlink" href="#dp-contests" title="Permanent link">&para;</a></h2>
6793+
<h2 id="dp-contests">DP Contests<a class="headerlink" href="#dp-contests" title="Permanent link">&para;</a></h2>
67926794
<ul>
67936795
<li><a href="https://atcoder.jp/contests/dp/tasks">Atcoder - Educational DP Contest</a></li>
67946796
<li><a href="https://cses.fi/problemset/list/">CSES - Dynamic Programming</a></li>
67956797
</ul>
67966798

67976799
<ul class="metadata page-metadata" data-bi-name="page info" lang="en-us" dir="ltr">
67986800
<span class="contributors-text">Contributors:</span>
6799-
<ul class="contributors" data-bi-name="contributors"><li><a href="https://github.com/mhayter" title="mhayter" data-bi-name="contributorprofile" target="_blank">mhayter</a> (80.61%)</li><li><a href="https://github.com/Zyad-Ayad" title="Zyad-Ayad" data-bi-name="contributorprofile" target="_blank">Zyad-Ayad</a> (11.52%)</li><li><a href="https://github.com/jakobkogler" title="jakobkogler" data-bi-name="contributorprofile" target="_blank">jakobkogler</a> (2.42%)</li><li><a href="https://github.com/ShubhamPhapale" title="ShubhamPhapale" data-bi-name="contributorprofile" target="_blank">ShubhamPhapale</a> (1.82%)</li><li><a href="https://github.com/adamant-pwn" title="adamant-pwn" data-bi-name="contributorprofile" target="_blank">adamant-pwn</a> (1.21%)</li><li><a href="https://github.com/Ahmed-Elshitehi" title="Ahmed-Elshitehi" data-bi-name="contributorprofile" target="_blank">Ahmed-Elshitehi</a> (1.21%)</li><li><a href="https://github.com/boredumbk" title="boredumbk" data-bi-name="contributorprofile" target="_blank">boredumbk</a> (0.61%)</li><li><a href="https://github.com/hitarth-gg" title="hitarth-gg" data-bi-name="contributorprofile" target="_blank">hitarth-gg</a> (0.61%)</li></ul>
6801+
<ul class="contributors" data-bi-name="contributors"><li><a href="https://github.com/mhayter" title="mhayter" data-bi-name="contributorprofile" target="_blank">mhayter</a> (79.39%)</li><li><a href="https://github.com/Zyad-Ayad" title="Zyad-Ayad" data-bi-name="contributorprofile" target="_blank">Zyad-Ayad</a> (9.7%)</li><li><a href="https://github.com/clumsy" title="clumsy" data-bi-name="contributorprofile" target="_blank">clumsy</a> (6.06%)</li><li><a href="https://github.com/ShubhamPhapale" title="ShubhamPhapale" data-bi-name="contributorprofile" target="_blank">ShubhamPhapale</a> (1.82%)</li><li><a href="https://github.com/Ahmed-Elshitehi" title="Ahmed-Elshitehi" data-bi-name="contributorprofile" target="_blank">Ahmed-Elshitehi</a> (1.21%)</li><li><a href="https://github.com/jakobkogler" title="jakobkogler" data-bi-name="contributorprofile" target="_blank">jakobkogler</a> (1.21%)</li><li><a href="https://github.com/adamant-pwn" title="adamant-pwn" data-bi-name="contributorprofile" target="_blank">adamant-pwn</a> (0.61%)</li></ul>
68006802
</ul>
68016803

68026804
</article>

0 commit comments

Comments
 (0)