<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Tabulation on IT Comparison</title><link>https://comparison.metacog.co.kr/tags/tabulation/</link><description>Recent content in Tabulation on IT Comparison</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 02 Aug 2026 23:46:25 +0900</lastBuildDate><atom:link href="https://comparison.metacog.co.kr/tags/tabulation/index.xml" rel="self" type="application/rss+xml"/><item><title>Memoization vs Tabulation: Top-Down vs Bottom-Up Dynamic Programming</title><link>https://comparison.metacog.co.kr/posts/2026-08-02-memoization-vs-tabulation-top-down-vs-bottom-up-dynamic-prog/</link><pubDate>Sun, 02 Aug 2026 23:46:25 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-02-memoization-vs-tabulation-top-down-vs-bottom-up-dynamic-prog/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;Both techniques avoid redundant recomputation in dynamic programming problems by caching subproblem results, but they build that cache in opposite directions. &lt;strong class="kw"&gt;Memoization&lt;/strong&gt; starts from the original problem and recurses downward, caching results lazily as calls return, while &lt;strong class="kw"&gt;tabulation&lt;/strong&gt; starts from the base cases and iterates upward, filling a table until the final answer is reached.&lt;/p&gt;
&lt;h2 id="comparison-diagram"&gt;Comparison Diagram&lt;/h2&gt;
&lt;div class="compare-diagram"&gt;
&lt;svg viewBox="0 0 640 360" xmlns="http://www.w3.org/2000/svg"&gt;&lt;line x1="320" y1="20" x2="320" y2="340" style="stroke:var(--border)" stroke-width="1" stroke-dasharray="4 4"/&gt;&lt;text x="160" y="28" text-anchor="middle" style="fill:var(--compare-a)" font-size="15" font-weight="bold"&gt;Memoization (Top-Down)&lt;/text&gt;&lt;line x1="160" y1="63" x2="100" y2="98" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;line x1="160" y1="63" x2="220" y2="98" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;line x1="100" y1="116" x2="65" y2="150" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;line x1="100" y1="116" x2="135" y2="150" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;line x1="220" y1="116" x2="190" y2="150" style="stroke:var(--border)" stroke-width="1.5" stroke-dasharray="3 3"/&gt;&lt;circle cx="160" cy="48" r="18" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="160" y="52" text-anchor="middle" style="fill:var(--content)" font-size="10"&gt;fib(4)&lt;/text&gt;&lt;circle cx="100" cy="105" r="18" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="100" y="109" text-anchor="middle" style="fill:var(--content)" font-size="10"&gt;fib(3)&lt;/text&gt;&lt;circle cx="220" cy="105" r="16" style="fill:var(--border);stroke:var(--border)" stroke-width="1.5" stroke-dasharray="2 2"/&gt;&lt;text x="220" y="109" text-anchor="middle" style="fill:var(--secondary)" font-size="9"&gt;fib(2)*&lt;/text&gt;&lt;circle cx="65" cy="155" r="16" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="65" y="159" text-anchor="middle" style="fill:var(--content)" font-size="9"&gt;fib(2)&lt;/text&gt;&lt;circle cx="135" cy="155" r="14" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="135" y="159" text-anchor="middle" style="fill:var(--content)" font-size="9"&gt;fib(1)&lt;/text&gt;&lt;text x="160" y="188" text-anchor="middle" style="fill:var(--secondary)" font-size="9"&gt;* = cache hit, no recompute&lt;/text&gt;&lt;rect x="40" y="200" width="240" height="75" rx="6" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="160" y="217" text-anchor="middle" style="fill:var(--primary)" font-size="11" font-weight="bold"&gt;memo cache&lt;/text&gt;&lt;text x="160" y="235" text-anchor="middle" style="fill:var(--content)" font-size="10"&gt;fib(0)=0 fib(1)=1&lt;/text&gt;&lt;text x="160" y="250" text-anchor="middle" style="fill:var(--content)" font-size="10"&gt;fib(2)=1 fib(3)=2&lt;/text&gt;&lt;text x="160" y="265" text-anchor="middle" style="fill:var(--content)" font-size="10"&gt;fib(4)=3&lt;/text&gt;&lt;text x="160" y="300" text-anchor="middle" style="fill:var(--secondary)" font-size="10"&gt;recurse down, cache on return&lt;/text&gt;&lt;text x="480" y="28" text-anchor="middle" style="fill:var(--compare-b)" font-size="15" font-weight="bold"&gt;Tabulation (Bottom-Up)&lt;/text&gt;&lt;path d="M345,100 L630,100" style="stroke:var(--compare-b);fill:none" stroke-width="1.5" marker-end="url(#arrowB)"/&gt;&lt;text x="487" y="88" text-anchor="middle" style="fill:var(--secondary)" font-size="10"&gt;for i = 0 .. n&lt;/text&gt;&lt;defs&gt;&lt;marker id="arrowB" markerWidth="8" markerHeight="8" refX="6" refY="3" orient="auto"&gt;&lt;path d="M0,0 L6,3 L0,6 Z" style="fill:var(--compare-b)"/&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;rect x="345" y="140" width="50" height="40" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="370" y="135" text-anchor="middle" style="fill:var(--content)" font-size="9"&gt;dp[0]&lt;/text&gt;&lt;text x="370" y="164" text-anchor="middle" style="fill:var(--content)" font-size="12"&gt;0&lt;/text&gt;&lt;rect x="405" y="140" width="50" height="40" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="430" y="135" text-anchor="middle" style="fill:var(--content)" font-size="9"&gt;dp[1]&lt;/text&gt;&lt;text x="430" y="164" text-anchor="middle" style="fill:var(--content)" font-size="12"&gt;1&lt;/text&gt;&lt;rect x="465" y="140" width="50" height="40" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="490" y="135" text-anchor="middle" style="fill:var(--content)" font-size="9"&gt;dp[2]&lt;/text&gt;&lt;text x="490" y="164" text-anchor="middle" style="fill:var(--content)" font-size="12"&gt;1&lt;/text&gt;&lt;rect x="525" y="140" width="50" height="40" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="550" y="135" text-anchor="middle" style="fill:var(--content)" font-size="9"&gt;dp[3]&lt;/text&gt;&lt;text x="550" y="164" text-anchor="middle" style="fill:var(--content)" font-size="12"&gt;2&lt;/text&gt;&lt;rect x="585" y="140" width="50" height="40" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="610" y="135" text-anchor="middle" style="fill:var(--content)" font-size="9"&gt;dp[4]&lt;/text&gt;&lt;text x="610" y="164" text-anchor="middle" style="fill:var(--content)" font-size="12"&gt;3&lt;/text&gt;&lt;line x1="395" y1="160" x2="405" y2="160" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;line x1="455" y1="160" x2="465" y2="160" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;line x1="515" y1="160" x2="525" y2="160" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;line x1="575" y1="160" x2="585" y2="160" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="610" y="200" text-anchor="middle" style="fill:var(--primary)" font-size="10" font-weight="bold"&gt;final answer&lt;/text&gt;&lt;text x="480" y="300" text-anchor="middle" style="fill:var(--secondary)" font-size="10"&gt;build up from base cases&lt;/text&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;h2 id="comparison-table"&gt;Comparison Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Memoization (Top-Down)&lt;/th&gt;
&lt;th&gt;Tabulation (Bottom-Up)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Entry point&lt;/td&gt;
&lt;td&gt;Starts from the original problem call, e.g. solve(n)&lt;/td&gt;
&lt;td&gt;Starts from the smallest base cases, e.g. dp[0], dp[1]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Control flow&lt;/td&gt;
&lt;td&gt;Recursive function calls, following the natural recurrence&lt;/td&gt;
&lt;td&gt;Iterative loop over subproblem indices in dependency order&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Subproblems computed&lt;/td&gt;
&lt;td&gt;Only those actually reachable from the initial call&lt;/td&gt;
&lt;td&gt;All subproblems up to the target, whether needed or not&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage structure&lt;/td&gt;
&lt;td&gt;Hash map or sparse cache keyed by call arguments&lt;/td&gt;
&lt;td&gt;Array or table indexed by subproblem parameters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Order dependency&lt;/td&gt;
&lt;td&gt;Implicit, resolved automatically by call stack ordering&lt;/td&gt;
&lt;td&gt;Explicit, programmer must sort iteration to respect dependencies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Call overhead&lt;/td&gt;
&lt;td&gt;Function call and stack frame cost per subproblem&lt;/td&gt;
&lt;td&gt;No function call overhead, just array reads and writes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stack risk&lt;/td&gt;
&lt;td&gt;Can hit recursion depth limits or stack overflow on deep inputs&lt;/td&gt;
&lt;td&gt;No recursion, so no stack depth concerns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code shape&lt;/td&gt;
&lt;td&gt;Mirrors the recursive definition, often easier to derive first&lt;/td&gt;
&lt;td&gt;Requires reformulating the recurrence as an explicit loop&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="key-differences"&gt;Key Differences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Memoization computes subproblems &lt;strong class="kw"&gt;on demand&lt;/strong&gt;, while tabulation computes every subproblem &lt;strong class="kw"&gt;exhaustively&lt;/strong&gt; in order.&lt;/li&gt;
&lt;li&gt;Memoization relies on the &lt;strong class="kw"&gt;call stack&lt;/strong&gt; to sequence work; tabulation relies on a manually ordered &lt;strong class="kw"&gt;loop&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Tabulation typically enables &lt;strong class="kw"&gt;space optimization&lt;/strong&gt; (e.g. keeping only the last few rows) since access order is known upfront.&lt;/li&gt;
&lt;li&gt;Memoization can be &lt;strong class="kw"&gt;stack-limited&lt;/strong&gt; on deep recursion, whereas tabulation avoids recursion entirely.&lt;/li&gt;
&lt;li&gt;Memoization is usually a smaller &lt;strong class="kw"&gt;code change&lt;/strong&gt; from a naive recursive solution; tabulation requires restructuring it as iteration.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="when-to-use-each"&gt;When to Use Each&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Memoization (Top-Down)&lt;/strong&gt;&lt;/p&gt;</description></item></channel></rss>