<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/rss.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Aditya Negi</title><description>Turning ideas into reality, one line of code at a time</description><link>https://adityanegi.com</link><item><title>Tree Data Structure: Basics</title><link>https://adityanegi.com/posts/tree-data-structure</link><guid isPermaLink="true">https://adityanegi.com/posts/tree-data-structure</guid><description>Learn about tree data structures, their properties, and terminologies.</description><pubDate>Thu, 02 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction to Trees&lt;/h2&gt;
&lt;p&gt;When learning data structures, &lt;strong&gt;trees&lt;/strong&gt; mark a turning point. They move us beyond linear structures like arrays and linked lists, into the world of &lt;strong&gt;hierarchical data&lt;/strong&gt; — a structure where relationships matter as much as values.&lt;/p&gt;
&lt;h3&gt;Why Trees Matter in Computer Science&lt;/h3&gt;
&lt;p&gt;Trees appear everywhere in computing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Hierarchical Data Representation&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;File systems (folders containing files and subfolders).&lt;/li&gt;
&lt;li&gt;XML/HTML documents (DOM tree).&lt;/li&gt;
&lt;li&gt;Organization charts.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Databases&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;B-trees and B+ trees form the backbone of most relational database indexes.&lt;/li&gt;
&lt;li&gt;Binary search trees (BSTs) for efficient searching.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Compilers &amp;amp; Parsing&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Abstract Syntax Trees (ASTs) represent the structure of source code.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Artificial Intelligence&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Decision trees and game trees power algorithms for planning and search.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Networking &amp;amp; Operating Systems&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Routing tables, memory allocation trees, process hierarchies.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In short, trees help us represent &lt;strong&gt;data with parent-child relationships&lt;/strong&gt; efficiently.&lt;/p&gt;
&lt;h3&gt;Where You’ll Encounter Trees&lt;/h3&gt;
&lt;p&gt;If you’re preparing for &lt;strong&gt;technical interviews&lt;/strong&gt; or doing &lt;strong&gt;competitive programming&lt;/strong&gt;, trees are unavoidable. Expect to see them in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LeetCode / Codeforces / HackerRank problems.&lt;/li&gt;
&lt;li&gt;Google, Meta, Amazon interviews (common focus on tree traversals, Lowest Common Ancestor, diameter, etc.).&lt;/li&gt;
&lt;li&gt;Competitive contests requiring &lt;strong&gt;efficient data queries&lt;/strong&gt; (segment trees, Fenwick trees).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mastering trees builds intuition that directly transfers to &lt;strong&gt;graph algorithms&lt;/strong&gt;, since a tree is just a special type of graph.&lt;/p&gt;
&lt;h3&gt;A Quick Mental Model&lt;/h3&gt;
&lt;p&gt;Here’s a simple way to think about trees in the broader landscape of data structures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Linked List&lt;/strong&gt; → A linear chain of nodes (like a train).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tree&lt;/strong&gt; → A branching structure of nodes (like a family tree).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Graph&lt;/strong&gt; → A general network of nodes and edges (like a city map).&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Basic Terminology in Trees&lt;/h2&gt;
&lt;p&gt;Before diving into traversals or algorithms, it’s important to understand the &lt;strong&gt;core terminology&lt;/strong&gt; of trees. These definitions will appear again and again, both in theory and in interview problems.&lt;/p&gt;
&lt;h3&gt;Node&lt;/h3&gt;
&lt;p&gt;A &lt;strong&gt;node&lt;/strong&gt; is the basic building block of a tree.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each node typically stores a &lt;strong&gt;value (or data)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;It may also have &lt;strong&gt;pointers (or references)&lt;/strong&gt; to its children.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example in code (binary tree node in TypeScript):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class TreeNode {
  val: number;
  left: TreeNode | null;
  right: TreeNode | null;

  constructor(val: number) {
    this.val = val;
    this.left = null;
    this.right = null;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Root&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The root is the topmost node in a tree.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It has no parent.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Every other node is a descendant of the root.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::viber
&lt;em&gt;Think of the C drive in your computer — all files and folders branch out from it.&lt;/em&gt;
:::&lt;/p&gt;
&lt;h3&gt;Parent, Child, and Sibling&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Parent&lt;/strong&gt; → is a node with one or more child nodes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Child&lt;/strong&gt; → is a node that descends from a parent.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Siblings&lt;/strong&gt; → are nodes that share the same parent.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::viber{align=&quot;right&quot;}
&lt;em&gt;Example: In a family tree, you and your brother are siblings because you share the same parent.&lt;/em&gt;
:::&lt;/p&gt;
&lt;h3&gt;Leaf&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;          A         &amp;lt;- Root
        /   \
       B     C     &amp;lt;- B and C are children of A (A is their parent)
      / \     \
     D   E     F &amp;lt;- D, E, F are leaf nodes (no children)

&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A leaf is a node that has no children.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Also called a terminal node.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::viber
&lt;em&gt;In a file system analogy, a file is usually a leaf, while folders are internal nodes.&lt;/em&gt;
:::&lt;/p&gt;
&lt;h3&gt;Height, Depth, and Level&lt;/h3&gt;
&lt;p&gt;These terms are often confused, so let’s clarify:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Depth of a node&lt;/strong&gt; → Distance from the root to that node (root has depth 0).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Height of a node&lt;/strong&gt; → Longest path from that node to a leaf.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Height of Tree&lt;/strong&gt; → Height of the root node.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Level of a node&lt;/strong&gt; → Depth + 1 (so the root is at level 1).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;        A (root)
       / \
      B   C
     / \
    D   E

Depth of A = 0

Depth of B = 1

Height of B = 1 (longest path to D or E)

Height of A = 2

Level of C = 2

&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Subtree&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A subtree is simply a tree within a tree.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Every node defines the root of its own subtree.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, in the above diagram, the node B and its children (D, E) form a subtree.&lt;/p&gt;
&lt;p&gt;:::viber
&lt;em&gt;Subtrees are essential when solving recursive tree problems, because you often break a tree down into its left and right subtrees.&lt;/em&gt;
:::&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Types of Trees&lt;/h2&gt;
&lt;p&gt;Trees can take many forms depending on how many children nodes each node has and how balanced the tree is. Understanding the different types of trees helps in choosing the right data structure for a problem.&lt;/p&gt;
&lt;h3&gt;General Tree&lt;/h3&gt;
&lt;p&gt;A general tree is a tree where a node can have any number of children.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        A
      / | \
     B  C  D
       / \
      E   F
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Node A has three children: B, C, and D.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Node C has two children: E and F.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There is no restriction on the number of children per node.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Binary Tree&lt;/h3&gt;
&lt;p&gt;A binary tree is a tree where each node has at most 2 children, commonly referred to as left and right.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
        A
       / \
      B   C
     / \
    D   E
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Node A has two children: B and C.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Node B has two children: D and E.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Node C has no children.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Full / Complete / Perfect Binary Trees&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Full Binary Tree&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every node has 0 or 2 children.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;
        A
       / \
      B   C
     / \
    D   E
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;C is a leaf, B has 2 children → satisfies full binary tree properties.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Complete Binary Tree&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All levels are completely filled except possibly the last, which is filled from left to right.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;
        A
       / \
      B   C
     / \  /
    D   E F
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Level 3 is partially filled, but nodes are filled left to right → complete binary tree.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Perfect Binary Tree&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All internal nodes have 2 children and all leaves are at the same level.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;
        A
       / \
      B   C
     / \ / \
    D  E F  G
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Fully balanced, no missing nodes → perfect binary tree.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Skewed Tree&lt;/h3&gt;
&lt;p&gt;A skewed tree is a tree where all nodes have only one child.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Left-skewed: each node has only a left child.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;Left-Skewed
    A
   /
  B
 /
C
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Right-skewed: each node has only a right child.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;Right-Skewed
A
 \
  B
   \
    C
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Skewed trees behave like linked lists.&lt;/li&gt;
&lt;li&gt;Traversals have worst-case time complexity of O(n).&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><author>Aditya Negi</author></item><item><title>Tree Data Structure: Traversals</title><link>https://adityanegi.com/posts/tree-traversals</link><guid isPermaLink="true">https://adityanegi.com/posts/tree-traversals</guid><description>Learn about different types of tree traversals.</description><pubDate>Fri, 03 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Tree Traversals&lt;/h2&gt;
&lt;p&gt;Tree traversal means visiting each node in a specific order.&lt;/p&gt;
&lt;p&gt;Two main categories:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Depth-First Search (DFS) → Preorder, Inorder, Postorder&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Breadth-First Search (BFS) → Level-order&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We’ll use this basic class written in Python for examples:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Preorder Traversal (Root → Left → Right)&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;       A
      / \
     B   C
    / \
   D   E

Preorder: A → B → D → E → C
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# Recursive
def preorder(node):
    if not node:
        return
    print(node.val)      # Root
    preorder(node.left)  # Left
    preorder(node.right) # Right

# Iterative
def preorder_iter(root):
    if not root:
        return
    stack = [root]
    while stack:
        node = stack.pop()
        print(node.val)
        if node.right:
            stack.append(node.right)
        if node.left:
            stack.append(node.left)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Inorder Traversal (Left → Root → Right)&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;       A
      / \
     B   C
    / \
   D   E

Inorder: D → B → E → A → C
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;
# Recursive
def preorder(node):
    if not node:
        return
    print(node.val)      # Root
    preorder(node.left)  # Left
    preorder(node.right) # Right

# Iterative
def preorder_iter(root):
    if not root:
        return
    stack = [root]
    while stack:
        node = stack.pop()
        print(node.val)
        if node.right:
            stack.append(node.right)
        if node.left:
            stack.append(node.left)

&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Postorder Traversal (Left → Right → Root)&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;
       A
      / \
     B   C
    / \
   D   E

Postorder: D → E → B → C → A
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# Recursive
def postorder(node):
    if not node:
        return
    postorder(node.left)   # Left
    postorder(node.right)  # Right
    print(node.val)        # Root

# Iterative
def postorder_iter(root):
    if not root:
        return
    stack, out = [root], []
    while stack:
        node = stack.pop()
        out.append(node.val)
        if node.left:
            stack.append(node.left)
        if node.right:
            stack.append(node.right)
    for val in reversed(out):
        print(val)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Level Order Traversal&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;
       A
      / \
     B   C
    / \
   D   E

Level Order: A → B → C → D → E

&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;from collections import deque

def level_order(root):
    if not root:
        return
    q = deque([root])
    while q:
        node = q.popleft()
        print(node.val)
        if node.left:
            q.append(node.left)
        if node.right:
            q.append(node.right)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Grouped Level Order&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Visit nodes level by level, left → right.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Group nodes per level.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;
        A
       / \
      B   C
     / \   \
    D   E   F

Level 1: [A]             -&amp;gt; Start with root
Level 2: [B, C]          -&amp;gt; Children of A
Level 3: [D, E, F]       -&amp;gt; Children of B and C

Output: [[A], [B, C], [D, E, F]]

&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;def level_order_grouped(root):
    res = []
    if not root:
        return res
    q = deque([root])
    while q:
        size = len(q)
        level = []
        for _ in range(size):
            node = q.popleft()
            level.append(node.val)
            if node.left:
                q.append(node.left)
            if node.right:
                q.append(node.right)
        res.append(level)
    return res
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Zigzag Level Order&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Visit nodes level by level, but alternate the order each level: left→right, right→left, left→right..&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;
        A
       / \
      B   C
     / \   \
    D   E   F

Level 1 (Left→Right):  [A]
Level 2 (Right→Left):  [C, B]
Level 3 (Left→Right):  [D, E, F]

Output: [[A], [C, B], [D, E, F]]
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;def zigzag_level_order(root):
    res = []
    if not root:
        return res
    q = deque([root])
    left_to_right = True
    while q:
        size = len(q)
        level = deque()
        for _ in range(size):
            node = q.popleft()
            if left_to_right:
                level.append(node.val)
            else:
                level.appendleft(node.val)
            if node.left:
                q.append(node.left)
            if node.right:
                q.append(node.right)
        res.append(list(level))
        left_to_right = not left_to_right
    return res
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><author>Aditya Negi</author></item><item><title>Leetcode 226: Inverting a Binary Tree</title><link>https://adityanegi.com/posts/inverting-a-binary-tree</link><guid isPermaLink="true">https://adityanegi.com/posts/inverting-a-binary-tree</guid><description>Invert a binary tree using recursive and iterative approaches, with step-by-step explanation and code examples in Python.</description><pubDate>Sat, 04 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Problem Statement&lt;/h2&gt;
&lt;p&gt;Given the root of a binary tree, invert the tree, and return its root.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://leetcode.com/problems/invert-binary-tree/description/&quot;&gt;Link To the Problem&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Intuition&lt;/h2&gt;
&lt;p&gt;A binary tree is a tree where each node has at most 2 children, commonly referred to as left and right.
Inverting a binary tree means swapping the left and right subtrees of every node.&lt;/p&gt;
&lt;h2&gt;Approach&lt;/h2&gt;
&lt;p&gt;We can solve this problem recursively or iteratively:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Recursive Approach (DFS):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If the current node is None, return None.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Swap the left and right children recursively:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set the left child to the result of inverting the original right subtree.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set the right child to the result of inverting the original left subtree.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Return the current node.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Iterative Approach (BFS):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Use a queue to perform level-order traversal.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For each node in the queue, swap its left and right children.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add non-null children to the queue for further processing.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Complexity&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time complexity:&lt;/strong&gt; &lt;strong&gt;O(n)&lt;/strong&gt;, where n is the number of nodes in the tree. Each node is visited exactly once.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Space complexity:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Recursive approach: &lt;strong&gt;O(h)&lt;/strong&gt; due to the recursion stack, where h is the height of the tree.&lt;/li&gt;
&lt;li&gt;Iterative approach: &lt;strong&gt;O(n)&lt;/strong&gt; in the worst case for the queue.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:

    # Recursive Implementation (DFS)
    def invert_tree_recursively(self, root: Optional[TreeNode]) -&amp;gt; Optional[TreeNode]:
        if not root :
            return 

        # swap the nodes in place
        root.left,root.right = self.invert_tree_recursively(root.right),self.invert_tree_recursively(root.left)

        return root 

    # Iterative Implementation (BFS)
     def invert_tree_iteratively(self, root: Optional[TreeNode]) -&amp;gt; Optional[TreeNode]:
        if not root:
            return None

        queue = deque([root])

        while queue:
            node = queue.popleft()
            
            # swap the nodes in place
            node.left, node.right = node.right, node.left
            
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)

        return root
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><author>Aditya Negi</author></item><item><title>Leetcode 100: Check if two binary tree are the same</title><link>https://adityanegi.com/posts/check-if-same-tree</link><guid isPermaLink="true">https://adityanegi.com/posts/check-if-same-tree</guid><description>Check if two binary trees are the same, with step-by-step explanation and code examples in Python.</description><pubDate>Sun, 05 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Problem Statement&lt;/h2&gt;
&lt;p&gt;Given the roots of two binary trees p and q, write a function to check if they are the same or not.&lt;/p&gt;
&lt;p&gt;Two binary trees are considered the same if they are structurally identical, and the nodes have the same value.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://leetcode.com/problems/same-tree/description/&quot;&gt;Link To the Problem&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Intuition&lt;/h2&gt;
&lt;p&gt;When comparing two binary trees, the key is to check structure and values at the same time.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If both nodes are None, they are identical in that position.&lt;/li&gt;
&lt;li&gt;If one node is None but the other isn’t, the trees differ.&lt;/li&gt;
&lt;li&gt;If both nodes exist, their values must be equal, and their left and right subtrees must also be the same.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Approach&lt;/h2&gt;
&lt;p&gt;We perform a recursive check:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Base case 1: If both nodes are None, return True.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Base case 2: If only one of them is None, return False.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Base case 3: If the values don’t match, return False.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Recursive step: Check if both left subtrees and right subtrees are identical.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This ensures both the structure and values of the trees are the same.&lt;/p&gt;
&lt;h2&gt;Complexity&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time complexity:&lt;/strong&gt; Each node is visited exactly once, so the complexity is O(n) where n is the number of nodes (minimum of the two trees).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Space complexity:&lt;/strong&gt;
The recursion depth depends on the height of the tree. In the worst case (skewed tree), the depth is O(n).
In the best case (balanced tree), it’s O(log n).
So, space complexity is O(h) where h is the height of the tree.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def is_same_tree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -&amp;gt; bool:

        if p is None and q is None :
            return True

        if p is None or q is None :
            return False

        if p.val != q.val :
            return False

        return self.is_same_tree(p.left,q.left) and self.is_same_tree(p.right,q.right)       
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><author>Aditya Negi</author></item><item><title>Leetcode 572: Subtree of Another Tree</title><link>https://adityanegi.com/posts/subtree-of-another-tree</link><guid isPermaLink="true">https://adityanegi.com/posts/subtree-of-another-tree</guid><description>Check if a binary tree is a subtree of another tree, with step-by-step explanation and code examples in Python.</description><pubDate>Sun, 12 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Problem Statement&lt;/h2&gt;
&lt;p&gt;Given the roots of two binary trees &lt;code&gt;root&lt;/code&gt; and subRoot, return true if there is a subtree of root with the same structure and node values of subRoot and false otherwise.&lt;/p&gt;
&lt;p&gt;A subtree of a binary tree tree is a tree that consists of a node in tree and all of this node&apos;s descendants. The tree tree could also be considered as a subtree of itself.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://leetcode.com/problems/subtree-of-another-tree/description/&quot;&gt;Link To the Problem&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Intuition&lt;/h2&gt;
&lt;p&gt;A binary tree is composed of nodes, each having up to two children.
To determine if one tree (&lt;code&gt;subRoot&lt;/code&gt;) is a subtree of another (&lt;code&gt;root&lt;/code&gt;), we need to check whether &lt;code&gt;subRoot&lt;/code&gt; appears exactly somewhere inside root.&lt;/p&gt;
&lt;p&gt;That means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;There must exist a node in &lt;code&gt;root&lt;/code&gt; such that the subtree rooted at that node is identical to &lt;code&gt;subRoot&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Two trees are identical if their node values and structure match perfectly.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Approach&lt;/h2&gt;
&lt;p&gt;We can solve this problem using a recursive approach:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Base idea:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Traverse the main tree (&lt;code&gt;root&lt;/code&gt;) node by node.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;At each node, check if the subtree starting there matches &lt;code&gt;subRoot&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;Helper function (compare)&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Compares two trees for equality.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Returns True only if both are None or if their values and corresponding children are identical.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;Recursive traversal (is_subtree)&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If the current subtree of &lt;code&gt;root&lt;/code&gt; matches &lt;code&gt;subRoot&lt;/code&gt;, return True.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Otherwise, recursively check the left and right subtrees of &lt;code&gt;root&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If no match is found, return False.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This approach effectively checks all possible subtree roots in the main tree.&lt;/p&gt;
&lt;h2&gt;Complexity&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time complexity:&lt;/strong&gt; &lt;strong&gt;O(m * n)&lt;/strong&gt;, where m = number of nodes in &lt;code&gt;root&lt;/code&gt; and n = number of nodes in &lt;code&gt;subRoot&lt;/code&gt;. For each node in &lt;code&gt;root&lt;/code&gt; , we may compare upto &lt;code&gt;n&lt;/code&gt; nodes in &lt;code&gt;subRoot&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Space complexity:&lt;/strong&gt; &lt;strong&gt;O(h)&lt;/strong&gt; due to the recursion stack, where h is the height of the tree.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def compare(self,node1,node2) :
        if not node1 and not node2 :
            return True

        if not node1 or not node2 :
            return False
        
        if node1.val != node2.val :
            return False

        return self.compare(node1.left,node2.left) and self.compare(node1.right,node2.right)

    def is_subtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -&amp;gt; bool:
        
        if self.compare(root,subRoot) :
            return True

        if root.left and self.is_subtree(root.left,subRoot):
            return True

        if root.right and self.is_subtree(root.right,subRoot) :
            return True

        return False
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><author>Aditya Negi</author></item><item><title>Leetcode 235: Lowest Common Ancestor of a Binary Search Tree</title><link>https://adityanegi.com/posts/lca-of-a-bst</link><guid isPermaLink="true">https://adityanegi.com/posts/lca-of-a-bst</guid><description>Find the lowest common ancestor of two nodes in a binary search tree, with step-by-step explanation and code examples in Python.</description><pubDate>Mon, 13 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Problem Statement&lt;/h2&gt;
&lt;p&gt;Given a binary search tree (BST), find the lowest common ancestor (LCA) node of two given nodes in the BST.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/description/&quot;&gt;Link To the Problem&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Intuition&lt;/h2&gt;
&lt;p&gt;When both target nodes p and q lie on the same side of the current node (either both in the left or both in the right subtree), the Lowest Common Ancestor (LCA) must also be on that side.&lt;/p&gt;
&lt;p&gt;However, when they diverge — one node is on the left and the other on the right (or one is equal to the current node) — the current node itself becomes their lowest common ancestor.&lt;/p&gt;
&lt;h2&gt;Approach&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Start from the root node.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If both p and q have values smaller than root.val, the LCA must be in the left subtree, so recurse left.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If both p and q have values greater than root.val, the LCA must be in the right subtree, so recurse right.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If the values diverge (i.e., one on each side, or one equals the root), then the current root is the LCA.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This logic works because of the Binary Search Tree (BST) property — left subtree values &amp;lt; root &amp;lt; right subtree values.&lt;/p&gt;
&lt;h2&gt;Complexity&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time complexity:&lt;/strong&gt; &lt;strong&gt;O(h)&lt;/strong&gt;, where h is where is the height of the tree.
&lt;ul&gt;
&lt;li&gt;In a balanced BST, h=log(n),&lt;/li&gt;
&lt;li&gt;In the worst case (skewed tree), h=n&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Space complexity:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Recursive approach: &lt;strong&gt;O(h)&lt;/strong&gt; due to the recursion stack, where h is the height of the tree.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def lowestCommonAncestor(self, root: &apos;TreeNode&apos;, p: &apos;TreeNode&apos;, q: &apos;TreeNode&apos;) -&amp;gt; &apos;TreeNode&apos;:
        # Base case: if the tree is empty
        if not root:
            return None

        # If both p and q are smaller, LCA is in the left subtree
        if p.val &amp;lt; root.val and q.val &amp;lt; root.val:
            return self.lowestCommonAncestor(root.left, p, q)

        # If both p and q are greater, LCA is in the right subtree
        elif p.val &amp;gt; root.val and q.val &amp;gt; root.val:
            return self.lowestCommonAncestor(root.right, p, q)

        # Otherwise, root is the split point — the LCA
        else:
            return root
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><author>Aditya Negi</author></item><item><title>Leetcode 199: Binary Tree Right Side View</title><link>https://adityanegi.com/posts/right-side-view-of-binary-tree</link><guid isPermaLink="true">https://adityanegi.com/posts/right-side-view-of-binary-tree</guid><description>Find the right side view of a binary tree, with step-by-step explanation and code examples in Python.</description><pubDate>Tue, 14 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Problem Statement&lt;/h2&gt;
&lt;p&gt;Given the root of a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://leetcode.com/problems/binary-tree-right-side-view/description/&quot;&gt;Link To the Problem&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Intuition&lt;/h2&gt;
&lt;p&gt;When viewing a binary tree from the right side, at each level of the tree, we only see the rightmost node. So, if we traverse the tree level by level (using Breadth-First Search), the last node encountered at each level will be visible from the right side.&lt;/p&gt;
&lt;h2&gt;Approach&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Use a queue (deque) to perform a level-order traversal (BFS).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For each level:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Process all nodes currently in the queue (those belonging to the same level).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Keep track of the last node’s value encountered at this level — that node will be visible from the right side.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add the value of the rightmost node from each level to the result list.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Return the result list after the traversal is complete.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Complexity&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time complexity:&lt;/strong&gt; Each node is visited exactly once, so the complexity is &lt;code&gt; O(n) where n is the number of nodes&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Space complexity:&lt;/strong&gt; &lt;code&gt;O(w) where w is the maximum width of the tree&lt;/code&gt; &lt;code&gt;(worst-case O(n) for a complete tree)&lt;/code&gt;, due to the queue used in BFS.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

from collections import deque

class Solution:
    def rightSideView(self, root: Optional[TreeNode]) -&amp;gt; List[int]:
        if not root:
            return []
        
        q = deque([root])
        res = []
        
        while q:
            n = len(q)
            for i in range(n):
                node = q.popleft()
                # If it&apos;s the last node in this level, add it to the result
                if i == n - 1:
                    res.append(node.val)
                if node.left:
                    q.append(node.left)
                if node.right:
                    q.append(node.right)
        
        return res    
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><author>Aditya Negi</author></item><item><title>Leetcode 1448: Count Good Nodes in Binary Tree</title><link>https://adityanegi.com/posts/count-good-notes-in-binary-tree</link><guid isPermaLink="true">https://adityanegi.com/posts/count-good-notes-in-binary-tree</guid><description>Given a binary tree root, a node X in the tree is named good if in the path from root to X there are no nodes with a value greater than X.</description><pubDate>Thu, 23 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Problem Statement&lt;/h2&gt;
&lt;p&gt;Given a binary tree root, a node X in the tree is named good if in the path from root to X there are no nodes with a value greater than X.&lt;/p&gt;
&lt;p&gt;Return the number of good nodes in the binary tree.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://leetcode.com/problems/count-good-nodes-in-binary-tree/description/&quot;&gt;Link To the Problem&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Intuition&lt;/h2&gt;
&lt;p&gt;A node is considered &lt;em&gt;good&lt;/em&gt; if, on the path from the root to that node, there are &lt;strong&gt;no nodes with a greater value&lt;/strong&gt; than it.&lt;/p&gt;
&lt;p&gt;So, as we traverse the tree, we can keep track of the &lt;strong&gt;maximum value encountered so far&lt;/strong&gt; along the path.&lt;br /&gt;
If the current node’s value is greater than or equal to this maximum, we count it as a “good” node.&lt;/p&gt;
&lt;h2&gt;Approach&lt;/h2&gt;
&lt;p&gt;We can solve this problem using &lt;strong&gt;Depth-First Search (DFS)&lt;/strong&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Start from the root and initialize the &lt;code&gt;max_until_now&lt;/code&gt; as negative infinity.&lt;/li&gt;
&lt;li&gt;At each node:
&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;node.val &amp;gt;= max_until_now&lt;/code&gt;, it’s a &lt;em&gt;good node&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Update the maximum for the next recursive calls as &lt;code&gt;max(max_until_now, node.val)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Recursively count the number of good nodes in the left and right subtrees.&lt;/li&gt;
&lt;li&gt;The total number of good nodes is the sum of:
&lt;ul&gt;
&lt;li&gt;1 (if the current node is good)&lt;/li&gt;
&lt;li&gt;number of good nodes in the left subtree&lt;/li&gt;
&lt;li&gt;number of good nodes in the right subtree.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Complexity&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time Complexity:&lt;/strong&gt;&lt;br /&gt;
&lt;code&gt;O(n)&lt;/code&gt;, since we visit every node exactly once.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Space Complexity:&lt;/strong&gt;&lt;br /&gt;
&lt;code&gt;O(h)&lt;/code&gt;, where h is the height of the tree (due to recursion stack).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Worst case (skewed tree): &lt;code&gt;O(n)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Best case (balanced tree): &lt;code&gt;O(\log n)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def goodNodes(self, root: TreeNode) -&amp;gt; int:

        def dfs(node, max_until_now):
            if not node:
                return 0

            res = 0
            if node.val &amp;gt;= max_until_now:
                res += 1

            new_max = max(max_until_now, node.val)
            res += dfs(node.left, new_max)
            res += dfs(node.right, new_max)

            return res

        return dfs(root, -float(&quot;inf&quot;))     
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><author>Aditya Negi</author></item></channel></rss>