<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Cell by Cell</title>
        <link>https://blog.evanzhou.org//</link>
        <description>Evan の Blog</description>
        <lastBuildDate>Tue, 02 Jun 2026 07:31:08 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en-US</language>
        <copyright>All rights reserved 2026, Evan Zhou</copyright>
        <item>
            <title><![CDATA[After 24 Kata: Learning To Ask A Better Question]]></title>
            <link>https://blog.evanzhou.org//tech/after-24-kata</link>
            <guid>https://blog.evanzhou.org//tech/after-24-kata</guid>
            <pubDate>Thu, 28 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[After the first 24 Kata exercises, the biggest lesson was not a specific algorithm, but learning to ask what information each step should produce.]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-36edbfeadaef80cf9920ec02cfb10c28"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-text notion-block-36edbfeadaef8034831ec225506dbe98">I started Kata as a problem-solving practice project.</div><div class="notion-text notion-block-36edbfeadaef809d85dfc83f506fb4df">The point was never to collect problems. The point was to practice the process of solving them: reading carefully, writing down a first idea, finding where that idea breaks, and then turning the rough reasoning into a clear solution.</div><div class="notion-text notion-block-36edbfeadaef8062ac75f0e055542f1b">After the first 24 kata, the most useful lesson is not a particular algorithm. It is this:</div><blockquote class="notion-quote notion-block-36edbfeadaef80e29c40c757ca7ea0bf"><div>A problem often becomes easier when I stop asking for the final answer directly and start asking what information each step should produce.</div></blockquote><div class="notion-text notion-block-36edbfeadaef800abe4df0dcf84d49dc">Full project: <a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://evanbio.github.io/kata/">Kata</a></div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-36edbfeadaef803489ced2764fb3ec95" data-id="36edbfeadaef803489ced2764fb3ec95"><span><div id="36edbfeadaef803489ced2764fb3ec95" class="notion-header-anchor"></div><a class="notion-hash-link" href="#36edbfeadaef803489ced2764fb3ec95" title="The First Pattern: Remember The Right Thing"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>The First Pattern: Remember The Right Thing</b></span></span></h3><div class="notion-text notion-block-36edbfeadaef80f58f15e3809169cd0b">The early problems were mostly about arrays, strings, and simple lookup.</div><div class="notion-text notion-block-36edbfeadaef80ffa69bdab4bc9de2be"><code class="notion-inline-code">001 · Two Sum</code> started with the obvious brute-force idea: check every pair. The better question was not:</div><blockquote class="notion-quote notion-block-36edbfeadaef8048a616fa27b6f1f8a9"><div>Which two numbers add to the target?</div></blockquote><div class="notion-text notion-block-36edbfeadaef8031bf18ecb2ceeb3c09">but:</div><blockquote class="notion-quote notion-block-36edbfeadaef80fdbe2bebb056875add"><div>If I am looking at this number, what complement would I need, and have I seen it before?</div></blockquote><div class="notion-text notion-block-36edbfeadaef8037bfe6ed7ac9ce22e8">That small change turns a nested loop into a single pass with a hash map.</div><div class="notion-text notion-block-36edbfeadaef80d881d6d46bd3a6f3b8">The same idea appears again in <code class="notion-inline-code">007 · Contains Duplicate</code>. If the only question is whether something appeared before, a <code class="notion-inline-code">set</code> is a better mental model than a list. A list stores values, but a set answers the question:</div><blockquote class="notion-quote notion-block-36edbfeadaef80b8869fc364bb2b700f"><div>Is this already here?</div></blockquote><div class="notion-text notion-block-36edbfeadaef80c09767edf22bbababc"><code class="notion-inline-code">004 · Valid Anagram</code> adds one more step. It is not enough to know whether a character appears. The count matters. So the right memory is not a set, but a frequency map.</div><div class="notion-text notion-block-36edbfeadaef80bab06ff0245b40ef78">These problems look simple, but they introduced an important habit:</div><blockquote class="notion-quote notion-block-36edbfeadaef8019bd61df418cb1330d"><div>Before choosing a data structure, define the question it needs to answer.</div></blockquote><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-36edbfeadaef80569fe9ea93f409c0f2" data-id="36edbfeadaef80569fe9ea93f409c0f2"><span><div id="36edbfeadaef80569fe9ea93f409c0f2" class="notion-header-anchor"></div><a class="notion-hash-link" href="#36edbfeadaef80569fe9ea93f409c0f2" title="Boundaries Matter More Than They Look"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>Boundaries Matter More Than They Look</b></span></span></h3><div class="notion-text notion-block-36edbfeadaef80ef874ed2b042c4db67">Several problems were really about boundaries.</div><div class="notion-text notion-block-36edbfeadaef80b1b47ee812f64c5e61">In <code class="notion-inline-code">003 · Binary Search</code>, the first instinct is to cut the array or look at the middle. But the real work is maintaining two boundaries, <code class="notion-inline-code">left</code> and <code class="notion-inline-code">right</code>, without losing the original index.</div><div class="notion-text notion-block-36edbfeadaef801d9ce3cff72b2480cc"><code class="notion-inline-code">012 · First Bad Version</code> made that sharper. The task is not just binary search for a value. It is finding the first position where a condition becomes true.</div><div class="notion-text notion-block-36edbfeadaef8093a196d6258a060013">That changes the update rules:</div><ul class="notion-list notion-list-disc notion-block-36edbfeadaef8036aaf5edd77fa1c32b"><li>if <code class="notion-inline-code">mid</code> is good, it cannot be the answer, so move to <code class="notion-inline-code">mid + 1</code></li></ul><ul class="notion-list notion-list-disc notion-block-36edbfeadaef80858ae0d6c4d3723bcf"><li>if <code class="notion-inline-code">mid</code> is bad, it might still be the first bad version, so keep it</li></ul><div class="notion-text notion-block-36edbfeadaef80da8e78dbce52e7449e">This is the part I want to remember: binary search is less about the middle element itself and more about what can be safely removed.</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-36edbfeadaef8024be8aee7d82e41d5b" data-id="36edbfeadaef8024be8aee7d82e41d5b"><span><div id="36edbfeadaef8024be8aee7d82e41d5b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#36edbfeadaef8024be8aee7d82e41d5b" title="When A Window Is Not The Right Window"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>When A Window Is Not The Right Window</b></span></span></h3><div class="notion-text notion-block-36edbfeadaef807087bfff2d2b2a5715"><code class="notion-inline-code">009 · Maximum Subarray</code> was one of the more useful early lessons.</div><div class="notion-text notion-block-36edbfeadaef800d86acf6387d328d6a">At first, it looks like a continuous interval problem. That makes it tempting to think in terms of a moving left boundary and right boundary:</div><blockquote class="notion-quote notion-block-36edbfeadaef80f0be94ce57140e130a"><div>Where should the best subarray start?</div></blockquote><div class="notion-text notion-block-36edbfeadaef807fa8d7d4e63fb9c4d1">But with negative numbers, the window does not behave in a clean monotonic way. Sometimes the correct move is not to shift the left boundary by one step. Sometimes the whole previous prefix should be abandoned.</div><div class="notion-text notion-block-36edbfeadaef802094e6fb1cbb50cbb7">The better question is:</div><blockquote class="notion-quote notion-block-36edbfeadaef80a0b307eb2707acec34"><div>What is the maximum subarray sum that must end at the current position?</div></blockquote><div class="notion-text notion-block-36edbfeadaef806aaec0c36156f6f4ec">That state is much easier to maintain:</div><div class="notion-text notion-block-36edbfeadaef80dd95a9cde909095f62">This was one of the first places where the solution stopped being about manually moving pointers and became about defining a state.</div><div class="notion-text notion-block-36edbfeadaef8021903ae20d57c8adba"><code class="notion-inline-code">011 · Climbing Stairs</code> had a similar shape. It can look like a counting or arrangement problem: how many <code class="notion-inline-code">1</code> steps and how many <code class="notion-inline-code">2</code> steps are used? But the cleaner question is:</div><blockquote class="notion-quote notion-block-36edbfeadaef8065b45bc960e8a6e98e"><div>What are the last possible moves into step <code class="notion-inline-code">n</code>?</div></blockquote><div class="notion-text notion-block-36edbfeadaef80e5aac8d63f247b0a26">The answer only depends on step <code class="notion-inline-code">n - 1</code> and step <code class="notion-inline-code">n - 2</code>.</div><div class="notion-text notion-block-36edbfeadaef8064a1d6e3f90de47d1f">That is a useful pattern: if listing all possibilities becomes messy, look for the smaller state that produces the current one.</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-36edbfeadaef80b1b852e4d6c1ef893d" data-id="36edbfeadaef80b1b852e4d6c1ef893d"><span><div id="36edbfeadaef80b1b852e4d6c1ef893d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#36edbfeadaef80b1b852e4d6c1ef893d" title="Pointers Are Not Values"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>Pointers Are Not Values</b></span></span></h3><div class="notion-text notion-block-36edbfeadaef80c29904dc3469b01089">The linked list problems were less about algorithms and more about understanding what a variable points to.</div><div class="notion-text notion-block-36edbfeadaef803bab5efaf7f92ea8ea">In <code class="notion-inline-code">006 · Merge Two Sorted Lists</code>, the key confusion is not the comparison itself. Comparing two current nodes is straightforward. The question is:</div><blockquote class="notion-quote notion-block-36edbfeadaef805285dff9c6b88e47b4"><div>Once I choose a node, where do I attach it?</div></blockquote><div class="notion-text notion-block-36edbfeadaef80b48dc0fa3366d3910f">That is why the <code class="notion-inline-code">dummy</code> node and <code class="notion-inline-code">tail</code> pointer matter. They make the result list easier to build without treating the first node as a special case.</div><div class="notion-text notion-block-36edbfeadaef8096a3eeeaeda8d05d19">In <code class="notion-inline-code">014 · Reverse Linked List</code>, the first confusion was more basic but more important:</div><blockquote class="notion-quote notion-block-36edbfeadaef807e99d7e5e52986e340"><div>Is <code class="notion-inline-code">head</code> the value, or the node?</div></blockquote><div class="notion-text notion-block-36edbfeadaef80b29401c7c9c9a69193">The solution only becomes clear after separating:</div><ul class="notion-list notion-list-disc notion-block-36edbfeadaef80d1836ac8c60ea46e08"><li><code class="notion-inline-code">current.val</code>: the value inside the node</li></ul><ul class="notion-list notion-list-disc notion-block-36edbfeadaef8059be43dd7823ca22b1"><li><code class="notion-inline-code">current.next</code>: the next node</li></ul><ul class="notion-list notion-list-disc notion-block-36edbfeadaef8034b9c3f69cff14d564"><li><code class="notion-inline-code">current = current.next</code>: moving the variable forward</li></ul><div class="notion-text notion-block-36edbfeadaef80c08c4ef23962e875f1">The actual reversal is not about printing values backward. It is about changing <code class="notion-inline-code">next</code> pointers.</div><div class="notion-text notion-block-36edbfeadaef80a888b0f0e2b0e60552">And before changing <code class="notion-inline-code">current.next</code>, the next node must be saved:</div><div class="notion-text notion-block-36edbfeadaef80e1a017e1f1d9085755">Otherwise the rest of the list is lost.</div><div class="notion-text notion-block-36edbfeadaef809bb1b4cca1fe29b85a"><code class="notion-inline-code">015 · Linked List Cycle</code> reinforced the same point from a different angle. A cycle is about seeing the same node object again, not seeing the same value again.</div><div class="notion-text notion-block-36edbfeadaef80eca0cef5272a4e34db">That distinction matters. In linked lists, values can repeat. Nodes are identities.</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-36edbfeadaef8090b35ff5a1f420cc1e" data-id="36edbfeadaef8090b35ff5a1f420cc1e"><span><div id="36edbfeadaef8090b35ff5a1f420cc1e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#36edbfeadaef8090b35ff5a1f420cc1e" title="Some Problems Are About The Local Rule"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>Some Problems Are About The Local Rule</b></span></span></h3><div class="notion-text notion-block-36edbfeadaef80b8adf5f7ed2317517c"><code class="notion-inline-code">013 · Roman to Integer</code> looked like a collection of special cases at first.</div><div class="notion-text notion-block-36edbfeadaef80f19f72de927ce3ff4b">There are many subtractive forms: <code class="notion-inline-code">IV</code>, <code class="notion-inline-code">IX</code>, <code class="notion-inline-code">XL</code>, <code class="notion-inline-code">XC</code>, <code class="notion-inline-code">CD</code>, <code class="notion-inline-code">CM</code>. It is tempting to handle them one by one.</div><div class="notion-text notion-block-36edbfeadaef80a6ba37e8d9094c65ff">But the common local rule is simpler:</div><blockquote class="notion-quote notion-block-36edbfeadaef807daeecd8c49f2f0acb"><div>If the current value is smaller than the value to its right, subtract it. Otherwise, add it.</div></blockquote><div class="notion-text notion-block-36edbfeadaef8042b68cd1f2d3c8e333">This is a good reminder that a problem with many named cases may still have one small rule underneath.</div><div class="notion-text notion-block-36edbfeadaef8067a8fae4d1828d92fe"><code class="notion-inline-code">017 · Plus One</code> had a similar lesson. The first reaction is:</div><blockquote class="notion-quote notion-block-36edbfeadaef8009b84de39752f2e787"><div>Is this just integer plus one?</div></blockquote><div class="notion-text notion-block-36edbfeadaef80c68085c4637a3c7131">Converting the whole digit array into an integer works in Python, but it avoids the real problem. The useful rule is local and starts at the end:</div><ul class="notion-list notion-list-disc notion-block-36edbfeadaef80a6ab4cc593b0581d03"><li>if the digit is not <code class="notion-inline-code">9</code>, add one and stop</li></ul><ul class="notion-list notion-list-disc notion-block-36edbfeadaef80f69cbee70298afc08a"><li>if the digit is <code class="notion-inline-code">9</code>, turn it into <code class="notion-inline-code">0</code> and continue the carry</li></ul><div class="notion-text notion-block-36edbfeadaef807b97a7d1d78129eea5">The problem is not about numbers in general. It is about how carry moves through an array.</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-36edbfeadaef8032a0bff4f975e7520d" data-id="36edbfeadaef8032a0bff4f975e7520d"><span><div id="36edbfeadaef8032a0bff4f975e7520d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#36edbfeadaef8032a0bff4f975e7520d" title="Tree Problems Changed The Main Question"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>Tree Problems Changed The Main Question</b></span></span></h3><div class="notion-text notion-block-36edbfeadaef80aba0edd300a6027fcd">The binary tree sequence was the biggest shift in this first batch.</div><div class="notion-text notion-block-36edbfeadaef80899d62fdbd833b7864"><code class="notion-inline-code">018 · Invert Binary Tree</code> starts with a simple idea:</div><blockquote class="notion-quote notion-block-36edbfeadaef8062bfc4d018ea2959c0"><div>Swap the left and right child of every node.</div></blockquote><div class="notion-text notion-block-36edbfeadaef804abb04f37121c7788a">The key is realizing that a tree is recursive:</div><div class="notion-text notion-block-36edbfeadaef80ccb2aacc8ae6275629">So the function only needs to handle the current root, then let the same function handle the subtrees.</div><div class="notion-text notion-block-36edbfeadaef808fbe65e99d4200a2f2"><code class="notion-inline-code">019 · Maximum Depth of Binary Tree</code> made the return value explicit:</div><blockquote class="notion-quote notion-block-36edbfeadaef80f9bf72c76dd7d1861b"><div><code class="notion-inline-code">maxDepth(root)</code> returns the maximum depth of the tree rooted at <code class="notion-inline-code">root</code>.</div></blockquote><div class="notion-text notion-block-36edbfeadaef808a873af7950f168a2f">Once that is clear, the relation is simple:</div><div class="notion-text notion-block-36edbfeadaef80119144ff4c97b707fe"><code class="notion-inline-code">020 · Same Tree</code> and <code class="notion-inline-code">021 · Symmetric Tree</code> pushed the same idea further. The useful move was to define the recursive function with the right arguments:</div><ul class="notion-list notion-list-disc notion-block-36edbfeadaef8029b61bcdde51baf4ce"><li><code class="notion-inline-code">isSameTree(p, q)</code> compares two current nodes</li></ul><ul class="notion-list notion-list-disc notion-block-36edbfeadaef8013b724d7788c59318b"><li><code class="notion-inline-code">isMirror(left, right)</code> compares two mirror positions</li></ul><div class="notion-text notion-block-36edbfeadaef80a28e67ebe42533b187">The function definition matters. If the function receives the right pieces of the problem, the recursive calls become much easier to write.</div><div class="notion-text notion-block-36edbfeadaef809e8461e40af94fe6af"><code class="notion-inline-code">022 · Subtree of Another Tree</code> then reused <code class="notion-inline-code">Same Tree</code>: one function checks whether two trees are identical, another function moves through <code class="notion-inline-code">root</code> looking for candidate starting points.</div><div class="notion-text notion-block-36edbfeadaef80c5ad8adf51f9bb3062">That separation is important:</div><ul class="notion-list notion-list-disc notion-block-36edbfeadaef8018813cc4d2ff262b5d"><li>one function answers &quot;are these two trees the same?&quot;</li></ul><ul class="notion-list notion-list-disc notion-block-36edbfeadaef8009b4cbd76486bd2e86"><li>another function answers &quot;does this tree contain a matching subtree?&quot;</li></ul><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-36edbfeadaef80acb75fe48308d6e93c" data-id="36edbfeadaef80acb75fe48308d6e93c"><span><div id="36edbfeadaef80acb75fe48308d6e93c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#36edbfeadaef80acb75fe48308d6e93c" title="The Clearest Lesson: Return Value vs Final Answer"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>The Clearest Lesson: Return Value vs Final Answer</b></span></span></h3><div class="notion-text notion-block-36edbfeadaef80899ef4c6e6e7078225">The strongest arc is:</div><ul class="notion-list notion-list-disc notion-block-36edbfeadaef80d897e3e588a8578523"><li><code class="notion-inline-code">019 · Maximum Depth of Binary Tree</code></li></ul><ul class="notion-list notion-list-disc notion-block-36edbfeadaef804d8770de5dc40c92d5"><li><code class="notion-inline-code">023 · Balanced Binary Tree</code></li></ul><ul class="notion-list notion-list-disc notion-block-36edbfeadaef80529eaae9b73b2d1d90"><li><code class="notion-inline-code">024 · Diameter of Binary Tree</code></li></ul><div class="notion-text notion-block-36edbfeadaef80cdb992dbc76fc6a6eb">They all use subtree height, but height plays a different role each time.</div><div class="notion-text notion-block-36edbfeadaef80bc8251e365c34564aa">In <code class="notion-inline-code">Maximum Depth</code>, height is the final answer.</div><div class="notion-text notion-block-36edbfeadaef806f8108c6ac68c36f36">In <code class="notion-inline-code">Balanced Binary Tree</code>, height is not enough by itself. The function needs to compute height while also detecting whether a subtree is already unbalanced. A special value like <code class="notion-inline-code">-1</code> can carry that failure state upward.</div><div class="notion-text notion-block-36edbfeadaef8082bdf9e9ea7670ab20">That taught me that a recursive return value does not have to be the final answer. It can be the information the parent call needs.</div><div class="notion-text notion-block-36edbfeadaef80bba49ffe759f6d7249"><code class="notion-inline-code">Diameter of Binary Tree</code> made this even clearer.</div><div class="notion-text notion-block-36edbfeadaef800fb4bde03f9960984e">The first thought was to ask whether the longest path goes through the root, or whether it sits inside the left or right subtree. That leads to awkward comparisons like:</div><blockquote class="notion-quote notion-block-36edbfeadaef80c89fdccedecc83433f"><div>Should I compare the two branches inside <code class="notion-inline-code">root.left</code> with the longest branch from <code class="notion-inline-code">root.right</code>?</div></blockquote><div class="notion-text notion-block-36edbfeadaef8087a150f6b7d1043b8b">This quickly mixes two different ideas:</div><ul class="notion-list notion-list-disc notion-block-36edbfeadaef8077b9c1e7d10c77682b"><li>the best diameter already formed inside a subtree</li></ul><ul class="notion-list notion-list-disc notion-block-36edbfeadaef80c58bbdf10b16b8e87d"><li>the single downward height that can be returned to a parent</li></ul><div class="notion-text notion-block-36edbfeadaef80fcae9fd463d40c851a">The better question is local:</div><blockquote class="notion-quote notion-block-36edbfeadaef80a096f1ca40c33d5f51"><div>For each node <code class="notion-inline-code">N</code>, if a candidate path has its highest point at <code class="notion-inline-code">N</code>, how long is that path?</div></blockquote><div class="notion-text notion-block-36edbfeadaef8089b8cdc9d8c46fe60d">Then the candidate length is:</div><div class="notion-text notion-block-36edbfeadaef80f3b9ccf8173cab484b">The recursive function still returns height. The final diameter is updated separately while visiting each node.</div><div class="notion-text notion-block-36edbfeadaef8045ba20c26aa7c8cd83">That distinction feels important enough to write down:</div><blockquote class="notion-quote notion-block-36edbfeadaef80529cc2e2684e9a98af"><div>The return value is what the parent needs. The final answer is what the whole problem asks for. They are not always the same thing.</div></blockquote><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-36edbfeadaef80f1a454d375093ad7f0" data-id="36edbfeadaef80f1a454d375093ad7f0"><span><div id="36edbfeadaef80f1a454d375093ad7f0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#36edbfeadaef80f1a454d375093ad7f0" title="What This Batch Taught Me"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>What This Batch Taught Me</b></span></span></h3><div class="notion-text notion-block-36edbfeadaef80cbb0a1eb6c18534e48">Looking across the first 24 kata, the repeated lesson is not &quot;use hash map&quot; or &quot;use recursion&quot; or &quot;use two pointers&quot;.</div><div class="notion-text notion-block-36edbfeadaef80c39c8be42615e63280">The repeated lesson is to ask a sharper question.</div><div class="notion-text notion-block-36edbfeadaef80a9a642f1b4f793b021">Instead of:</div><blockquote class="notion-quote notion-block-36edbfeadaef8012a00cf7aee7c4519a"><div>How do I find the answer?</div></blockquote><div class="notion-text notion-block-36edbfeadaef80d79b19d39634c91f2c">ask:</div><blockquote class="notion-quote notion-block-36edbfeadaef8065a675cea2bc50f518"><div>What information do I need at this step?</div></blockquote><div class="notion-text notion-block-36edbfeadaef8091a522fa9d5731c301">Instead of:</div><blockquote class="notion-quote notion-block-36edbfeadaef8064830efd40167d4212"><div>Which case is the answer in?</div></blockquote><div class="notion-text notion-block-36edbfeadaef802fa0d6d9e6cd13536d">ask:</div><blockquote class="notion-quote notion-block-36edbfeadaef80ef9a20e56f2ec4a990"><div>Can I define a local rule that covers all cases?</div></blockquote><div class="notion-text notion-block-36edbfeadaef8099afc9ccedf757bb67">Instead of:</div><blockquote class="notion-quote notion-block-36edbfeadaef807c85e7f0b8239b9eba"><div>What should the code look like?</div></blockquote><div class="notion-text notion-block-36edbfeadaef8018a79cdabc7df18a98">ask:</div><blockquote class="notion-quote notion-block-36edbfeadaef802bbae0f01352bb5559"><div>What should this variable or function mean?</div></blockquote><div class="notion-text notion-block-36edbfeadaef80b5af1ff2bd7c92d396">That is the part I want Kata to keep training.</div><div class="notion-text notion-block-36edbfeadaef8000b758e96c62675836">Full project: <a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://evanbio.github.io/kata/">Kata</a></div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Welcome to My Blog]]></title>
            <link>https://blog.evanzhou.org//life/welcome</link>
            <guid>https://blog.evanzhou.org//life/welcome</guid>
            <pubDate>Sat, 04 Jan 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[“Not all those who wander are lost.” This is the beginning of my journey to explore both the world and myself.]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-171dbfeadaef80c78f0ce305bb41de15"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-text notion-block-171dbfeadaef809ea95ed7cdbc0af8b1"><b>Hello, Blog!</b></div><div class="notion-text notion-block-171dbfeadaef80aa8485f57a68880a2c">Hi there, it’s me! Finally here, talking to… well, myself. But hey, isn’t that how all good blogs start? A little bit of monologuing, a sprinkle of awkward introductions, and boom—you’ve got yourself a blog.</div><div class="notion-text notion-block-171dbfeadaef80d791c4daf520f760ca">So, what’s this about? Honestly, I’m still figuring it out. But for now, let’s call it a cozy corner for all my random musings—life updates, tech experiments, creative detours, and whatever else pops into my mind.</div><h4 class="notion-h notion-h3 notion-h-indent-0 notion-block-171dbfeadaef80b688ddd7ca946368e8" data-id="171dbfeadaef80b688ddd7ca946368e8"><span><div id="171dbfeadaef80b688ddd7ca946368e8" class="notion-header-anchor"></div><a class="notion-hash-link" href="#171dbfeadaef80b688ddd7ca946368e8" title="Why a Blog?"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Why a Blog?</span></span></h4><div class="notion-text notion-block-171dbfeadaef80d2a31dc2d15c9c60e2">Because why not? I mean, what’s cooler than having a tiny slice of the internet where you can scream into the void and occasionally get an echo back?</div><div class="notion-text notion-block-171dbfeadaef803bbec3e4bcbb8dec53">Okay, okay, it’s not <em>just</em> that. I wanted a space to:</div><ul class="notion-list notion-list-disc notion-block-171dbfeadaef80379b0de8bb1cd2d4ea"><li>Share my adventures (the real ones and the ones in my head).</li></ul><ul class="notion-list notion-list-disc notion-block-171dbfeadaef80cea0f0cebc59a39344"><li>Document my attempts to tame the wild beast called technology.</li></ul><ul class="notion-list notion-list-disc notion-block-171dbfeadaef8025964dd8d5c0747a2d"><li>Connect with cool humans (yes, that’s you).</li></ul><h4 class="notion-h notion-h3 notion-h-indent-0 notion-block-171dbfeadaef804197f5e24f157ce3ae" data-id="171dbfeadaef804197f5e24f157ce3ae"><span><div id="171dbfeadaef804197f5e24f157ce3ae" class="notion-header-anchor"></div><a class="notion-hash-link" href="#171dbfeadaef804197f5e24f157ce3ae" title="What to Expect?"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">What to Expect?</span></span></h4><div class="notion-text notion-block-171dbfeadaef80ac93d9e0dab260575d">Chaos. Beautiful, organized chaos.</div><ul class="notion-list notion-list-disc notion-block-171dbfeadaef801e8d5ccebe231ff4af"><li><b>Life snippets</b>: Funny stories, random thoughts, maybe even some heartfelt ones if I’m feeling brave.</li></ul><ul class="notion-list notion-list-disc notion-block-171dbfeadaef8052b7c9c19d140ddb4b"><li><b>Tech stuff</b>: My trials and (many) errors in coding, AI, and trying to make machines smarter than me.</li></ul><ul class="notion-list notion-list-disc notion-block-171dbfeadaef80a89100eeda2fda4d06"><li><b>Creative bits</b>: Who knows, maybe I’ll write a poem or share a doodle. No promises, though.</li></ul><h4 class="notion-h notion-h3 notion-h-indent-0 notion-block-171dbfeadaef809a9defc4d1dcc21408" data-id="171dbfeadaef809a9defc4d1dcc21408"><span><div id="171dbfeadaef809a9defc4d1dcc21408" class="notion-header-anchor"></div><a class="notion-hash-link" href="#171dbfeadaef809a9defc4d1dcc21408" title="Final Words for This Awkward Hello"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Final Words for This Awkward Hello</span></span></h4><div class="notion-text notion-block-171dbfeadaef8061b508f5bbc08dc72a">So, here we are, at the start of this little blogging experiment. Will it be profound? Probably not. Will it be fun? I sure hope so.</div><div class="notion-text notion-block-171dbfeadaef80879660db25d9c7e3cd">If you’ve made it this far, welcome aboard! Let’s see where this ride takes us. And if nobody reads this but me, well… Hi, future me. You’re doing great (probably).</div><div class="notion-text notion-block-171dbfeadaef8033be6febae335e2797">Cheers,</div><div class="notion-text notion-block-171dbfeadaef80729d33c2fb8aaac76e">Me.</div></main></div>]]></content:encoded>
        </item>
    </channel>
</rss>