<?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>Algorithms on IT Comparison</title><link>https://comparison.metacog.co.kr/tags/algorithms/</link><description>Recent content in Algorithms 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/algorithms/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><item><title>Recursion vs Iteration: Two Ways to Repeat Work</title><link>https://comparison.metacog.co.kr/posts/2026-08-02-recursion-vs-iteration-two-ways-to-repeat-work/</link><pubDate>Sun, 02 Aug 2026 23:45:29 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-02-recursion-vs-iteration-two-ways-to-repeat-work/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;Both techniques repeat a computation until some condition is met, but they do it through fundamentally different mechanisms. &lt;strong class="kw"&gt;Recursion&lt;/strong&gt; repeats by having a function call itself on the call stack, while &lt;strong class="kw"&gt;iteration&lt;/strong&gt; repeats by looping over the same stack frame. The choice affects memory usage, readability, and how deep a computation can safely go.&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;defs&gt;&lt;marker id="arrA" markerWidth="8" markerHeight="8" refX="4" refY="4" orient="auto"&gt;&lt;path d="M0,0 L8,4 L0,8 z" style="fill:var(--compare-a)"/&gt;&lt;/marker&gt;&lt;marker id="arrB" markerWidth="8" markerHeight="8" refX="4" refY="4" orient="auto"&gt;&lt;path d="M0,0 L8,4 L0,8 z" style="fill:var(--compare-b)"/&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;line x1="320" y1="20" x2="320" y2="340" style="stroke:var(--border)" stroke-width="1.5" stroke-dasharray="4 4"/&gt;&lt;text x="160" y="36" text-anchor="middle" style="fill:var(--primary)" font-size="18" font-weight="bold"&gt;Recursion&lt;/text&gt;&lt;text x="480" y="36" text-anchor="middle" style="fill:var(--primary)" font-size="18" font-weight="bold"&gt;Iteration&lt;/text&gt;&lt;text x="160" y="58" text-anchor="middle" style="fill:var(--secondary)" font-size="11"&gt;call stack&lt;/text&gt;&lt;rect x="60" y="66" width="200" height="32" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="160" y="87" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;f(n)&lt;/text&gt;&lt;rect x="60" y="104" width="200" height="32" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="160" y="125" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;f(n-1)&lt;/text&gt;&lt;rect x="60" y="142" width="200" height="32" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="160" y="163" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;f(n-2)&lt;/text&gt;&lt;rect x="60" y="180" width="200" height="26" rx="4" style="fill:none;stroke:var(--border)" stroke-width="1.5" stroke-dasharray="4 3"/&gt;&lt;text x="160" y="197" text-anchor="middle" style="fill:var(--secondary)" font-size="13"&gt;...&lt;/text&gt;&lt;line x1="278" y1="70" x2="278" y2="200" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrA)"/&gt;&lt;text x="160" y="230" text-anchor="middle" style="fill:var(--secondary)" font-size="12"&gt;new frame per call&lt;/text&gt;&lt;text x="160" y="300" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;O(n) stack memory&lt;/text&gt;&lt;text x="160" y="318" text-anchor="middle" style="fill:var(--secondary)" font-size="11"&gt;risk: stack overflow&lt;/text&gt;&lt;text x="480" y="58" text-anchor="middle" style="fill:var(--secondary)" font-size="11"&gt;loop body (single frame)&lt;/text&gt;&lt;rect x="390" y="140" width="180" height="40" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="480" y="165" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;while / for&lt;/text&gt;&lt;path d="M 560 185 C 560 225 400 225 400 185" style="stroke:var(--compare-b);fill:none" stroke-width="1.5" marker-end="url(#arrB)"/&gt;&lt;text x="480" y="245" text-anchor="middle" style="fill:var(--secondary)" font-size="12"&gt;i++, same frame reused&lt;/text&gt;&lt;text x="480" y="300" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;O(1) stack memory&lt;/text&gt;&lt;text x="480" y="318" text-anchor="middle" style="fill:var(--secondary)" font-size="11"&gt;no growth per cycle&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;Recursion&lt;/th&gt;
&lt;th&gt;Iteration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Core mechanism&lt;/td&gt;
&lt;td&gt;Function calls itself with a smaller subproblem&lt;/td&gt;
&lt;td&gt;Explicit loop (for/while) repeats a block of code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Termination condition&lt;/td&gt;
&lt;td&gt;A base case stops further calls&lt;/td&gt;
&lt;td&gt;A loop condition evaluates to false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;State storage&lt;/td&gt;
&lt;td&gt;Held implicitly in parameters and locals of each stack frame&lt;/td&gt;
&lt;td&gt;Held explicitly in variables updated each pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory usage&lt;/td&gt;
&lt;td&gt;O(n) call stack space, one new frame per call&lt;/td&gt;
&lt;td&gt;O(1) auxiliary space, the same frame is reused&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failure mode&lt;/td&gt;
&lt;td&gt;Stack overflow on deep or unbounded recursion&lt;/td&gt;
&lt;td&gt;Infinite loop if the condition never turns false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance overhead&lt;/td&gt;
&lt;td&gt;Function-call overhead per level unless tail-call optimized&lt;/td&gt;
&lt;td&gt;No call overhead, just a branch/jump back&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best-fit problems&lt;/td&gt;
&lt;td&gt;Tree/graph traversal, divide-and-conquer, backtracking&lt;/td&gt;
&lt;td&gt;Linear, bounded repetition like counting or array scans&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;Recursion breaks a problem into &lt;strong class="kw"&gt;self-similar subcalls&lt;/strong&gt;; iteration repeats a block via an explicit loop.&lt;/li&gt;
&lt;li&gt;Recursion grows the &lt;strong class="kw"&gt;call stack&lt;/strong&gt; by one frame per call; iteration reuses a single frame.&lt;/li&gt;
&lt;li&gt;Deep recursion risks &lt;strong class="kw"&gt;stack overflow&lt;/strong&gt;, while iteration&amp;rsquo;s main failure mode is an infinite loop.&lt;/li&gt;
&lt;li&gt;Some languages apply &lt;strong class="kw"&gt;tail-call optimization&lt;/strong&gt; to turn tail recursion into iteration under the hood.&lt;/li&gt;
&lt;li&gt;Recursion maps naturally onto &lt;strong class="kw"&gt;trees and graphs&lt;/strong&gt;; iteration suits flat, bounded repetition.&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;Recursion&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>BFS vs DFS: Traversal Order and Data Structure</title><link>https://comparison.metacog.co.kr/posts/2026-08-02-bfs-vs-dfs-traversal-order-and-data-structure/</link><pubDate>Sun, 02 Aug 2026 23:44:09 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-02-bfs-vs-dfs-traversal-order-and-data-structure/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;Both are algorithms for visiting every node in a tree or graph, but they differ in which node they explore next. &lt;strong class="kw"&gt;BFS&lt;/strong&gt; spreads outward level by level using a queue, while &lt;strong class="kw"&gt;DFS&lt;/strong&gt; plunges down one path as far as possible before backtracking, using a stack.&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.5" stroke-dasharray="5,5"/&gt;&lt;text x="160" y="28" text-anchor="middle" style="fill:var(--primary)" font-size="18" font-weight="bold"&gt;BFS&lt;/text&gt;&lt;text x="480" y="28" text-anchor="middle" style="fill:var(--primary)" font-size="18" font-weight="bold"&gt;DFS&lt;/text&gt;&lt;line x1="160" y1="50" x2="100" y2="120" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;line x1="160" y1="50" x2="220" y2="120" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;line x1="100" y1="120" x2="70" y2="190" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;line x1="100" y1="120" x2="130" y2="190" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;line x1="220" y1="120" x2="190" y2="190" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;line x1="220" y1="120" x2="250" y2="190" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;circle cx="160" cy="50" r="16" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="160" y="55" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;1&lt;/text&gt;&lt;circle cx="100" cy="120" r="16" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="100" y="125" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;2&lt;/text&gt;&lt;circle cx="220" cy="120" r="16" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="220" y="125" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;3&lt;/text&gt;&lt;circle cx="70" cy="190" r="16" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="70" y="195" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;4&lt;/text&gt;&lt;circle cx="130" cy="190" r="16" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="130" y="195" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;5&lt;/text&gt;&lt;circle cx="190" cy="190" r="16" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="190" y="195" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;6&lt;/text&gt;&lt;circle cx="250" cy="190" r="16" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="250" y="195" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;7&lt;/text&gt;&lt;line x1="480" y1="50" x2="420" y2="120" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;line x1="480" y1="50" x2="540" y2="120" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;line x1="420" y1="120" x2="390" y2="190" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;line x1="420" y1="120" x2="450" y2="190" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;line x1="540" y1="120" x2="510" y2="190" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;line x1="540" y1="120" x2="570" y2="190" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;circle cx="480" cy="50" r="16" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="480" y="55" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;1&lt;/text&gt;&lt;circle cx="420" cy="120" r="16" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="420" y="125" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;2&lt;/text&gt;&lt;circle cx="540" cy="120" r="16" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="540" y="125" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;5&lt;/text&gt;&lt;circle cx="390" cy="190" r="16" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="390" y="195" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;3&lt;/text&gt;&lt;circle cx="450" cy="190" r="16" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="450" y="195" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;4&lt;/text&gt;&lt;circle cx="510" cy="190" r="16" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="510" y="195" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;6&lt;/text&gt;&lt;circle cx="570" cy="190" r="16" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="570" y="195" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;7&lt;/text&gt;&lt;rect x="60" y="260" width="28" height="24" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;rect x="92" y="260" width="28" height="24" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;rect x="124" y="260" width="28" height="24" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;rect x="156" y="260" width="28" height="24" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;rect x="188" y="260" width="28" height="24" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="20" y="277" style="fill:var(--secondary)" font-size="11"&gt;out&lt;/text&gt;&lt;text x="232" y="277" style="fill:var(--secondary)" font-size="11"&gt;in&lt;/text&gt;&lt;text x="140" y="305" text-anchor="middle" style="fill:var(--secondary)" font-size="13"&gt;Queue (FIFO)&lt;/text&gt;&lt;rect x="466" y="228" width="56" height="22" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;rect x="466" y="252" width="56" height="22" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;rect x="466" y="276" width="56" height="22" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;rect x="466" y="300" width="56" height="22" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="535" y="243" style="fill:var(--secondary)" font-size="11"&gt;push/pop&lt;/text&gt;&lt;text x="494" y="340" text-anchor="middle" style="fill:var(--secondary)" font-size="13"&gt;Stack (LIFO)&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;BFS&lt;/th&gt;
&lt;th&gt;DFS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Underlying structure&lt;/td&gt;
&lt;td&gt;Queue (FIFO)&lt;/td&gt;
&lt;td&gt;Stack (FILO), often via recursion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Traversal pattern&lt;/td&gt;
&lt;td&gt;Explores all neighbors at current depth before going deeper&lt;/td&gt;
&lt;td&gt;Follows one branch to its end before backtracking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Order nodes are visited&lt;/td&gt;
&lt;td&gt;Level by level (breadth-first)&lt;/td&gt;
&lt;td&gt;Branch by branch (depth-first)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory usage&lt;/td&gt;
&lt;td&gt;O(width) — can be large for wide/bushy graphs&lt;/td&gt;
&lt;td&gt;O(depth) — can be large for deep graphs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shortest path guarantee&lt;/td&gt;
&lt;td&gt;Yes, on unweighted graphs (first visit = shortest path)&lt;/td&gt;
&lt;td&gt;No, may find a longer path first&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Implementation style&lt;/td&gt;
&lt;td&gt;Iterative with explicit queue&lt;/td&gt;
&lt;td&gt;Recursive, or iterative with explicit stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Risk of infinite loop&lt;/td&gt;
&lt;td&gt;Low with visited-set on cyclic graphs&lt;/td&gt;
&lt;td&gt;Higher on cyclic graphs without visited-set, or infinite depth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical use cases&lt;/td&gt;
&lt;td&gt;Shortest path, level-order processing, web crawling by hops&lt;/td&gt;
&lt;td&gt;Topological sort, cycle detection, maze/backtracking problems&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;&lt;strong class="kw"&gt;BFS&lt;/strong&gt; uses a queue and expands outward level by level, while &lt;strong class="kw"&gt;DFS&lt;/strong&gt; uses a stack (or recursion) and dives deep before backtracking.&lt;/li&gt;
&lt;li&gt;BFS guarantees the &lt;strong class="kw"&gt;shortest path&lt;/strong&gt; on unweighted graphs; DFS does not.&lt;/li&gt;
&lt;li&gt;BFS memory cost scales with graph &lt;strong class="kw"&gt;width&lt;/strong&gt;, while DFS memory cost scales with graph &lt;strong class="kw"&gt;depth&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;DFS naturally supports &lt;strong class="kw"&gt;backtracking&lt;/strong&gt; algorithms like maze solving and topological sort.&lt;/li&gt;
&lt;li&gt;Both require a &lt;strong class="kw"&gt;visited set&lt;/strong&gt; to avoid infinite loops on cyclic graphs.&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;BFS&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Two Pointers vs Sliding Window: Choosing the Right Array Scanning Technique</title><link>https://comparison.metacog.co.kr/posts/2026-08-02-two-pointers-vs-sliding-window-choosing-the-right-array-scan/</link><pubDate>Sun, 02 Aug 2026 23:43:16 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-02-two-pointers-vs-sliding-window-choosing-the-right-array-scan/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;Two Pointers and Sliding Window are both O(n) techniques for scanning arrays or strings, but they solve different shapes of problems: Two Pointers tracks two independent &lt;strong class="kw"&gt;indices&lt;/strong&gt; that move toward, away from, or alongside each other, while Sliding Window maintains a contiguous &lt;strong class="kw"&gt;subrange&lt;/strong&gt; that expands and contracts as it scans. Picking the wrong one usually means either overcomplicating a pair-search problem or missing the running aggregate a window naturally provides.&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;defs&gt;&lt;marker id="arrowA" 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-a)"/&gt;&lt;/marker&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;text x="160" y="36" text-anchor="middle" font-size="18" style="fill:var(--primary)"&gt;Two Pointers&lt;/text&gt;&lt;text x="480" y="36" text-anchor="middle" font-size="18" style="fill:var(--primary)"&gt;Sliding Window&lt;/text&gt;&lt;line x1="320" y1="20" x2="320" y2="340" stroke-width="1" stroke-dasharray="4,4" style="stroke:var(--border)"/&gt;&lt;g&gt;&lt;rect x="40" y="150" width="28" height="40" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;rect x="72" y="150" width="28" height="40" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;rect x="104" y="150" width="28" height="40" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;rect x="136" y="150" width="28" height="40" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;rect x="168" y="150" width="28" height="40" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;rect x="200" y="150" width="28" height="40" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;rect x="232" y="150" width="28" height="40" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;rect x="264" y="150" width="28" height="40" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="54" y="176" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;L&lt;/text&gt;&lt;text x="278" y="176" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;R&lt;/text&gt;&lt;line x1="60" y1="215" x2="130" y2="215" stroke-width="2" marker-end="url(#arrowA)" style="stroke:var(--compare-a)"/&gt;&lt;line x1="272" y1="215" x2="202" y2="215" stroke-width="2" marker-end="url(#arrowA)" style="stroke:var(--compare-a)"/&gt;&lt;text x="166" y="270" text-anchor="middle" font-size="12" style="fill:var(--secondary)"&gt;indices converge inward&lt;/text&gt;&lt;text x="166" y="288" text-anchor="middle" font-size="12" style="fill:var(--secondary)"&gt;over sorted data&lt;/text&gt;&lt;/g&gt;&lt;g&gt;&lt;rect x="424" y="150" width="92" height="40" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;rect x="360" y="150" width="28" height="40" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;rect x="392" y="150" width="28" height="40" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;rect x="424" y="150" width="28" height="40" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;rect x="456" y="150" width="28" height="40" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;rect x="488" y="150" width="28" height="40" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;rect x="520" y="150" width="28" height="40" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;rect x="552" y="150" width="28" height="40" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;rect x="584" y="150" width="28" height="40" style="fill:none;stroke:var(--border)" stroke-width="1"/&gt;&lt;text x="424" y="176" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;L&lt;/text&gt;&lt;text x="512" y="176" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;R&lt;/text&gt;&lt;line x1="522" y1="170" x2="552" y2="170" stroke-width="2" marker-end="url(#arrowB)" style="stroke:var(--compare-b)" stroke-dasharray="3,3"/&gt;&lt;text x="486" y="270" text-anchor="middle" font-size="12" style="fill:var(--secondary)"&gt;contiguous range expands/&lt;/text&gt;&lt;text x="486" y="288" text-anchor="middle" font-size="12" style="fill:var(--secondary)"&gt;contracts, tracking an aggregate&lt;/text&gt;&lt;/g&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;Two Pointers&lt;/th&gt;
&lt;th&gt;Sliding Window&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Core mechanism&lt;/td&gt;
&lt;td&gt;Two independent indices scan or converge across the data&lt;/td&gt;
&lt;td&gt;Two indices (left/right) define a contiguous range that grows and shrinks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pointer movement&lt;/td&gt;
&lt;td&gt;Move toward each other, away, or in lockstep at a fixed offset&lt;/td&gt;
&lt;td&gt;Right pointer expands the range forward, left pointer contracts it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Input requirement&lt;/td&gt;
&lt;td&gt;Usually needs sorted data or a paired structure&lt;/td&gt;
&lt;td&gt;Works on any unsorted array or string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;State tracked&lt;/td&gt;
&lt;td&gt;Just the two positions and the values being compared&lt;/td&gt;
&lt;td&gt;A running aggregate of window contents (sum, count, frequency map)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Problem signature&lt;/td&gt;
&lt;td&gt;Pair-sum, palindrome check, merging two sorted arrays&lt;/td&gt;
&lt;td&gt;Longest/shortest substring or max/min sum under a constraint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Relationship between pointers&lt;/td&gt;
&lt;td&gt;No notion of a range between them, only the two positions matter&lt;/td&gt;
&lt;td&gt;The range between the pointers IS the answer candidate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time and space complexity&lt;/td&gt;
&lt;td&gt;O(n) time, O(1) space&lt;/td&gt;
&lt;td&gt;O(n) time, O(1) to O(k) space for the aggregate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failure mode&lt;/td&gt;
&lt;td&gt;Breaks if data isn&amp;rsquo;t sorted or orderable for the comparison&lt;/td&gt;
&lt;td&gt;Breaks if the target condition isn&amp;rsquo;t monotonic, so the window can&amp;rsquo;t shrink safely&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;Two Pointers tracks two independent &lt;strong class="kw"&gt;indices&lt;/strong&gt;; Sliding Window tracks a contiguous &lt;strong class="kw"&gt;range&lt;/strong&gt; between them.&lt;/li&gt;
&lt;li&gt;Two Pointers typically requires &lt;strong class="kw"&gt;sorted input&lt;/strong&gt;; Sliding Window works fine on unsorted sequences.&lt;/li&gt;
&lt;li&gt;Sliding Window maintains a running &lt;strong class="kw"&gt;aggregate&lt;/strong&gt; as it moves; Two Pointers usually just compares individual values.&lt;/li&gt;
&lt;li&gt;Sliding Window breaks down when the target condition isn&amp;rsquo;t &lt;strong class="kw"&gt;monotonic&lt;/strong&gt;, since the window can&amp;rsquo;t be safely shrunk.&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;Two Pointers&lt;/strong&gt;&lt;/p&gt;</description></item></channel></rss>