Prashant Barahi Algorithms Documentation

website·Indexed 32 days ago

https://prashantbarahi.com.np/

A collection of algorithm implementations and problem solutions covering topics such as linked lists, stacks, queues, and sorting. Includes code examples in Kotlin, Python, and Java for problems like HeapSort, Palindrome Permutation, and various LeetCode challenges.

Tokens
129.8K
Snippets
368
Records
391
Agent score
61%

What's inside Prashant Barahi Algorithms

  1. Overview of AVL Trees

    An AVL Tree is a self-balancing binary search tree where the heights of the two child subtrees of any node differ by at most one. This ensures the tree remains balanced, maintaining logarithmic time complexity for lookup, insertion, and deletion operations.
  2. Advanced summarizer CLI options

    You can override the default model for a specific run using the --model flag or enter an interactive session to ask follow-up questions about the content using the --ask flag.
    # Override the model for a single run
    summarizer --model claude-opus-4-8 https://example.com/article
    
    # Ask follow-up questions about the summary
    summarizer https://example.com/article --ask
  3. Understand Escape Analysis for memory and query optimization

    Escape Analysis is a compiler optimization technique used to determine if a variable created within a function escapes the scope of that function. If a variable does not escape (i.e., it is not returned or shared with a caller), it can be allocated on the stack instead of the heap for better efficiency. This concept can be applied manually by developers to optimize data retrieval, such as limiting SQL queries to only the fields used within a local scope.
  4. Solve the Unique Paths II problem with obstacles

    The Unique Paths II problem requires finding the number of unique paths from the top-left corner to the bottom-right corner of an m x n grid. The robot can only move down or right. The grid contains obstacles (marked as 1) and empty spaces (marked as 0). If the start or end cell contains an obstacle, no paths are possible.
  5. Implement a RandomizedSet with O(1) operations

    The RandomizedSet class provides a data structure that supports inserting, removing, and retrieving a random element, all with an average time complexity of O(1).

    Supported operations:

    • insert(val): Adds an integer to the set. Returns true if the element was not already present, false otherwise.
    • remove(val): Removes an integer from the set. Returns true if the element was present, false otherwise.
    • getRandom(): Returns a random element currently stored in the set.
  6. Advanced summarizer CLI options

    Use the --model flag to override the default LLM for a specific run. Use the --ask flag to enter an interactive mode where you can ask follow-up questions about the summarized content.
    # Override the model for a specific request
    summarizer --model claude-opus-4-8 https://example.com/article
    
    # Summarize and enter interactive Q&A mode
    summarizer https://example.com/article --ask
  7. Understand K-d Tree basics

    A K-d tree (k-dimensional tree) is a space-partitioning data structure used for organizing points in a k-dimensional space. It functions as a binary search tree that extends the concept of binary search to more than one dimension.
  8. Implement a basic Node class for linked lists in Python

    The Node class is a fundamental building block for linked list data structures. It stores a value (data) and a reference to the next node in the sequence (next), which defaults to None. It includes string representation methods for easier debugging and printing.
    class Node:
        def __init__(self, data):
            self.data = data
            self.next = None
    
        def __str__(self):
            return f"Node({self.data}, {self.next})"
    
        def __repr__(self):
            return str(self)
  9. Find the First Common Ancestor in a Bidirectional Tree

    To find the first common ancestor of two nodes in a tree where nodes maintain a reference to their parent, follow these steps:

    1. Calculate Depth: Determine the depth of both target nodes by traversing up to the root using the parent reference.
    2. Align Depths: Calculate the difference in depth between the two nodes. Move the deeper node up the tree (towards the root) until both nodes are at the same depth.
    3. Simultaneous Ascent: Move both nodes up to their respective parents one step at a time. The first node they both encounter that is identical is the First Common Ancestor.
    package graphs;
    
    import graphs.commons.BidirectionalTree;
    
    class FirstCommonAncestor {
        // Returns the depth of a node relative to the root
        static Integer depth(BidirectionalTree tree) {
            BidirectionalTree current = tree;
            int count = 0;
            while (current.parent != null) {
                current = current.parent;
                count++;
            }
            return count;
        }
    
        // Moves a node up the tree by a specified number of levels
        static BidirectionalTree goUpBy(BidirectionalTree tree, int times) {
            BidirectionalTree current = tree;
            for (int i = 1; i <= Math.abs(times); i++) {
                current = current.parent;
            }
            return current;
        }
    
        // Finds the first common ancestor of two nodes at the same depth
        static BidirectionalTree commonAncestor(BidirectionalTree t1, BidirectionalTree t2) {
            BidirectionalTree current1 = t1;
            BidirectionalTree current2 = t2;
    
            while (current1 != current2) {
                current1 = current1.parent;
                current2 = current2.parent;
            }
            return current1;
        }
    
        public static void main(final String[] args) {
            // Example setup: BidirectionalTree(parent, data)
            final BidirectionalTree tree = new BidirectionalTree(null, 10);
            tree.left = new BidirectionalTree(tree, 20);
            tree.right = new BidirectionalTree(tree, 80);
            
            // ... tree construction ...
    
            BidirectionalTree p = // node 1
            BidirectionalTree q = // node 2
    
            int delta = depth(p) - depth(q);
            BidirectionalTree t1 = p;
            BidirectionalTree t2 = q;
    
            if (delta < 0) {
                t2 = goUpBy(q, delta);
            } else if (delta > 0) {
                t1 = goUpBy(p, delta);
            }
    
            BidirectionalTree lca = commonAncestor(t1, t2);
            System.out.println("Common Ancestor: " + lca.data);
        }
    }
  10. Find the middle node of a singly-linked list using the Fast and Slow Pointer approach

    To find the middle node of a singly-linked list, use two pointers: a 'slow' pointer and a 'fast' pointer. Both start at the head of the list. The slow pointer moves one node at a time, while the fast pointer moves two nodes at a time. When the fast pointer reaches the end of the list, the slow pointer will be positioned at the middle node.
    private fun LinkedListNode.getMiddleNode(): LinkedListNode {
        var slowPointer: LinkedListNode = this
        var fastPointer: LinkedListNode? = this
    
        while (fastPointer?.next != null) {
            slowPointer = slowPointer.next!!
            fastPointer = fastPointer.next?.next
        }
        return slowPointer
    }