Sign Up Sign Up


Have an account? Sign In Now

Sign In Sign In


Forgot Password?

Don't have account, Sign Up Here

Forgot Password Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.


Have an account? Sign In Now

You must login to ask a question.


Forgot Password?

Need An Account, Sign Up Here

You must login to add post.


Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

RTSALL Logo RTSALL Logo
Sign InSign Up

RTSALL

RTSALL Navigation

  • Home
  • Tools
    • Run Code
    • JSON Beautifier
    • Regex Tester
    • Diff Checker
    • JWT Decoder
    • UUID Generator
    • .htaccess Generator
    • YAML/JSON Converter
    • SQL Formatter
    • Cron Generator
    • JSON to CSV/Excel
    • System Design Estimator
  • DSA
    • All DSA Problems
    • Online C++ Runner
    • Arrays, Strings & Cache
    • Two Pointers & Sliding Window
    • Linked Lists & Custom Allocators
    • Stacks, Queues & Ring Buffers
    • Trees, BSTs & Indexes
    • Tries & Prefix Search
    • Heaps & Priority Schedulers
    • Hashing & Collision Resolution
    • Graphs & Network Topologies
    • Dynamic Programming
    • Advanced Bitmask & Tree DP
    • Greedy & Resource Allocation
    • Binary Search & State Spaces
    • Bit Manipulation & Low-Level
    • System-Scale & Probabilistic
  • AI Utilities
    • Token Counter
    • JSON Schema Compiler
    • Fine-Tuning JSONL Converter
    • Vector RAG Playground
    • Prompt Optimizer & Architect
    • LLM GPU VRAM Calculator
  • Finance Tools
    • Compound Interest Calculator
    • Simple Interest Calculator
    • Present Value (PV) Calculator
    • Future Value (FV) Calculator
    • NPV Calculator
    • IRR Calculator
    • CAGR Calculator
    • Dividend Income Calculator
    • Yield on Cost Calculator
    • Dividend Payout Ratio
    • WACC Calculator
    • CAPM & Cost of Equity
    • Cost of Debt Calculator
    • DCF Valuation Calculator
    • Enterprise Value Calculator
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Tools
    • Run Code
    • JSON Beautifier
    • Regex Tester
    • Diff Checker
    • JWT Decoder
    • UUID Generator
    • .htaccess Generator
    • YAML/JSON Converter
    • SQL Formatter
    • Cron Generator
    • JSON to CSV/Excel
    • System Design Estimator
  • DSA
    • All DSA Problems
    • Online C++ Runner
    • Arrays, Strings & Cache
    • Two Pointers & Sliding Window
    • Linked Lists & Custom Allocators
    • Stacks, Queues & Ring Buffers
    • Trees, BSTs & Indexes
    • Tries & Prefix Search
    • Heaps & Priority Schedulers
    • Hashing & Collision Resolution
    • Graphs & Network Topologies
    • Dynamic Programming
    • Advanced Bitmask & Tree DP
    • Greedy & Resource Allocation
    • Binary Search & State Spaces
    • Bit Manipulation & Low-Level
    • System-Scale & Probabilistic
  • AI Utilities
    • Token Counter
    • JSON Schema Compiler
    • Fine-Tuning JSONL Converter
    • Vector RAG Playground
    • Prompt Optimizer & Architect
    • LLM GPU VRAM Calculator
  • Finance Tools
    • Compound Interest Calculator
    • Simple Interest Calculator
    • Present Value (PV) Calculator
    • Future Value (FV) Calculator
    • NPV Calculator
    • IRR Calculator
    • CAGR Calculator
    • Dividend Income Calculator
    • Yield on Cost Calculator
    • Dividend Payout Ratio
    • WACC Calculator
    • CAPM & Cost of Equity
    • Cost of Debt Calculator
    • DCF Valuation Calculator
    • Enterprise Value Calculator
  • About Us
  • Blog
  • Contact Us

Data Structures & Algorithms

Master core and advanced data structures and algorithms with production-grade implementations, hardware-conscious optimizations, and real-world system designs.

Share
  • Facebook
0 Followers
54 Answers
30 Questions
Home/Data Structures & Algorithms
  • Recent Questions
  • Most Answered
  • Answers
  • No Answers
  • Most Visited
  • Most Voted
  • Random
  1. Asked: September 11, 2026In: System-Scale & Probabilistic Structures

    pgvector: HNSW index build fails with out-of-memory or high swap: How to tune maintenance_work_mem & parallel workers

    aarav0
    aarav0
    Added an answer on September 11, 2026 at 9:57 pm

    Direct Technical Solution: Unlike IVFFlat (which partitions vector spaces with k-means centroids), HNSW (Hierarchical Navigable Small World) constructs a multi-layer proximity graph in physical RAM during build time. For 2,000,000 vectors with 1,536 dimensions, the raw vectors alone occupy 2,000,000Read more

    Direct Technical Solution: Unlike IVFFlat (which partitions vector spaces with k-means centroids), HNSW (Hierarchical Navigable Small World) constructs a multi-layer proximity graph in physical RAM during build time. For 2,000,000 vectors with 1,536 dimensions, the raw vectors alone occupy 2,000,000 × 1,536 × 4 bytes = 12.28 GB. Adding the HNSW graph neighbor connectivity lists (with m=16) increases total build RAM requirement to approximately 18 to 22 GB.

    1. The Formula to Calculate Required `maintenance_work_mem`

    Required RAM (Bytes) ≈ Rows × ((dimensions × 4) + (8 × M)) × 1.2 (Index Graph Overhead)

    2. PostgreSQL Configuration Tuning

    Temporarily allocate sufficient RAM to the session before triggering the index build, and utilize parallel CPU worker cores to accelerate graph edge exploration:

    -- Execute inside the active database session before CREATE INDEX:
    SET maintenance_work_mem = '24GB';
    SET max_parallel_maintenance_workers = 4;
    SET max_parallel_workers = 8;
    
    -- Now trigger the HNSW index build
    CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_documents_hnsw
    ON documents USING hnsw (embedding vector_cosine_ops) 
    WITH (m = 16, ef_construction = 64);
    
    -- Reset back to default after build completes
    RESET maintenance_work_mem;

    3. When to Use IVFFlat vs HNSW

    MetricHNSW IndexIVFFlat Index
    Build RAM RequirementHigh (18–24 GB for 2M vectors)Low (2–4 GB)
    Query Latency (QPS)Sub-5ms (Blazing fast graph traversal)15–50ms (Linear list scan)
    Recall Accuracy98%+ true nearest neighbors85–92% (Approximate centroid scan)
    See less
    • 0
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
  2. Asked: September 11, 2026In: Arrays, Strings & Cache Memory

    Why does std::views::filter on temporary containers trigger undefined behavior and dangling references in C++20?

    Abhishek
    Abhishek Begginer
    Added an answer on September 11, 2026 at 9:57 pm

    Direct Technical Solution: In C++20, range view adaptors (like std::views::filter, std::views::transform, and std::views::take) are strictly non-owning view wrappers. They do not duplicate or take ownership of the underlying container; they only store iterators pointing directly into the underlyingRead more

    Direct Technical Solution: In C++20, range view adaptors (like std::views::filter, std::views::transform, and std::views::take) are strictly non-owning view wrappers. They do not duplicate or take ownership of the underlying container; they only store iterators pointing directly into the underlying sequence.

    In your code, getTemperatures() returns a temporary std::vector<int> by value. At the semicolon ending the initialization expression auto warm_days = getTemperatures() | ...;, the temporary vector reaches the end of its full-expression lifetime and is immediately destructed. Consequently, the iterators stored inside warm_days become dangling pointers into deallocated stack/heap memory, causing undefined behavior upon iteration.

    Modern C++20 Fix (Lifetime Preservation)

    #include <iostream>
    #include <vector>
    #include <ranges>
    
    std::vector<int> getTemperatures() {
        return {18, 25, 32, 14, 29, 36};
    }
    
    int main() {
        // Solution 1: Bind the temporary to a named local variable
        // This extends the container lifetime across the entire scope.
        const auto temps = getTemperatures();
        auto warm_days = temps | std::views::filter([](int t) { return t > 20; });
    
        std::cout << "Warm days: ";
        for (int t : warm_days) {
            std::cout << t << " ";
        }
        std::cout << "
    ";
    
        return 0;
    }
    See less
    • 0
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
  3. Asked: September 11, 2026In: Bit Manipulation & Low-Level Computing

    PyTorch RuntimeError: CUDA out of memory: Why torch.cuda.empty_cache() fails & how to fix fragmentation

    Anonymous
    Anonymous Begginer
    Added an answer on September 11, 2026 at 9:57 pm

    Direct Technical Solution: torch.cuda.empty_cache() releases only cached (unallocated) blocks back to the CUDA driver; it never frees memory occupied by active tensors (weights, optimizer states, computation graph nodes). Calling it inside your training loop hurts performance because CUDA must constRead more

    Direct Technical Solution: torch.cuda.empty_cache() releases only cached (unallocated) blocks back to the CUDA driver; it never frees memory occupied by active tensors (weights, optimizer states, computation graph nodes). Calling it inside your training loop hurts performance because CUDA must constantly re-allocate OS memory via costly system calls.

    1. Root Cause: PyTorch Allocator Memory Fragmentation

    Look closely at your error message: 18.21 GiB allocated + 4.80 GiB reserved. PyTorch had nearly 5 GB of memory held in its internal caching allocator, but it was split into scattered, non-contiguous memory chunks. When a tensor required 512 MiB of contiguous VRAM, the allocator failed to find a single chunk large enough.

    2. The Modern Fix: Expandable Segments (PyTorch 2.0+)

    The definitive solution in modern PyTorch is activating virtual memory management via the expandable_segments flag. This instructs CUDA to map physical memory pages to a contiguous virtual memory space, virtually eliminating memory fragmentation:

    # Terminal / Docker Entrypoint (Set before launching Python)
    export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
    
    # Or directly in Python before calling any CUDA operations:
    import os
    os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "expandable_segments:True"
    import torch

    3. The 4 Golden Rules to Prevent CUDA OOM

    • Detach Loss Values: Never accumulate raw tensor losses: total_loss += loss retains the entire backward computation graph in VRAM! Always use total_loss += loss.item().
    • Use Automatic Mixed Precision (AMP): Halve activation memory using native BF16/FP16:
      with torch.autocast(device_type="cuda", dtype=torch.bfloat16):
          outputs = model(inputs)
          loss = criterion(outputs, targets)
    • Gradient Accumulation: Instead of a batch size of 64 that OOMs, use a micro-batch size of 16 and accumulate gradients across 4 backward steps:
      loss = loss / 4
      loss.backward()
      if (step + 1) % 4 == 0:
          optimizer.step()
          optimizer.zero_grad(set_to_none=True)
    • Zero Gradients with `set_to_none=True`: optimizer.zero_grad(set_to_none=True) deallocates memory instead of zeroing tensors with zeros of equal size.
    See less
    • 0
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
  4. Asked: September 11, 2026In: Data Structures & Algorithms

    Next.js 15: Error: Route used “params” without awaiting it (Asynchronous Page Props Fix)

    Abhay Tiwari
    Abhay Tiwari Begginer
    Added an answer on September 11, 2026 at 9:57 pm

    Direct Technical Solution: In Next.js 15, dynamic route parameters (params) and search parameters (searchParams) transitioned from synchronous plain JavaScript objects to native Promises. This breaking change was implemented to support React 19 Server Components and the new Partial Prerendering (PPRRead more

    Direct Technical Solution: In Next.js 15, dynamic route parameters (params) and search parameters (searchParams) transitioned from synchronous plain JavaScript objects to native Promises. This breaking change was implemented to support React 19 Server Components and the new Partial Prerendering (PPR) model, where the server renders the static page skeleton before dynamic parameters resolve.

    1. Server Component Migration (Async/Await)

    In all Next.js 15 Server Components (the default in the app/ directory), type params as a Promise and explicitly await it before accessing any key:

    // app/blog/[slug]/page.tsx (Next.js 15 Server Component)
    interface PageProps {
      params: Promise<{ slug: string }>;
      searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
    }
    
    export default async function BlogPostPage({ params, searchParams }: PageProps) {
      // Await the asynchronous params promise
      const { slug } = await params;
      const resolvedSearchParams = await searchParams;
    
      return (
        <main style={{ padding: "2rem" }}>
          <h1>Article: {slug}</h1>
          <p>Tracking Tag: {resolvedSearchParams.ref || "Direct Visit"}</p>
        </main>
      );
    }

    2. Client Component Migration (React 19 `use()` Hook)

    If your page file uses "use client", you cannot make the component function async. Instead, unwrap the params Promise using React 19’s native React.use() hook:

    // app/dashboard/[userId]/client-page.tsx
    "use client";
    
    import { use } from "react";
    
    interface ClientPageProps {
      params: Promise<{ userId: string }>;
    }
    
    export default function UserDashboard({ params }: ClientPageProps) {
      // Unwrap the promise synchronously within render
      const { userId } = use(params);
    
      return <div>Active User Session: {userId}</div>;
    }

    3. Comparison: Next.js 14 vs Next.js 15

    FeatureNext.js 14Next.js 15 (React 19)
    Props Type{ slug: string } (Synchronous Object)Promise<{ slug: string }> (Async Promise)
    Server UnwrappingDirect dot-access (params.slug)const { slug } = await params;
    Client UnwrappinguseParams() hookuse(params) or useParams()
    See less
    • 0
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
  5. Asked: September 11, 2026In: Data Structures & Algorithms, Greedy & Resource Allocation

    Task Scheduler with Cooldowns: Closed-form mathematical formula vs Priority Queue simulation

    Anonymous
    Anonymous Begginer
    Added an answer on September 11, 2026 at 9:54 am

    The Task Scheduler problem is a masterclass in recognizing that the most frequent task dictates the entire schedule structure. 1. Deriving the Formula Visually Suppose our tasks are [A, A, A, B, B, C] with cooldown n = 2. Task A appears most frequently ($count = 3$). Between each A, there must be atRead more

    The Task Scheduler problem is a masterclass in recognizing that the most frequent task dictates the entire schedule structure.

    1. Deriving the Formula Visually

    Suppose our tasks are [A, A, A, B, B, C] with cooldown n = 2.

    Task A appears most frequently ($count = 3$). Between each A, there must be at least n = 2 cooldown slots:

    Frame 1: A _ _
    Frame 2: A _ _
    Frame 3: A (last occurrence doesn't need trailing cooldown!)
    

    Notice the structure:

    • There are max_freq - 1 full frames.
    • Each full frame has size n + 1 (the task itself plus its n cooldown slots).
    • The final frame only contains the final occurrences of the most frequent tasks.

    2. The Closed-Form Equation

    Let max_freq be the highest frequency of any task, and max_count be how many tasks tie for that highest frequency (for example, if both A and B appear 3 times, max_count = 2).

    theoretical_min = (max_freq - 1) * (n + 1) + max_count
    

    What if there are so many other tasks that no CPU idle slots are needed?

    If you have tons of diverse tasks (e.g. [A, A, B, B, C, D, E, F, G, H]), they easily fill up all idle slots, and the CPU never needs to idle at all! In that case, the answer is simply len(tasks).

    Therefore, the global answer is simply:

    ans = max(len(tasks), (max_freq - 1) * (n + 1) + max_count)
    

    Clean Python 3.12 Implementation (0 CPU Simulation Cycles!)

    from collections import Counter
    
    def least_interval(tasks: list[str], n: int) -> int:
        """Calculates minimum task intervals in O(N) time and O(1) space."""
        counts = Counter(tasks)
        max_freq = max(counts.values())
        
        # Count how many tasks have this maximum frequency
        max_count = sum(1 for count in counts.values() if count == max_freq)
    
        # Calculate optimal frames
        formula_ans = (max_freq - 1) * (n + 1) + max_count
    
        # Answer is whichever is larger: formula or total task count
        return max(len(tasks), formula_ans)
    

    Complexity Breakdown

    • Time Complexity: O(N) to count task frequencies. The mathematical formula itself evaluates in O(1) time!
    • Space Complexity: O(1) auxiliary space, because the alphabet size is bounded by 26 English uppercase letters.
    See less
    • 0
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
  6. Asked: September 11, 2026In: Data Structures & Algorithms, Stacks, Queues & Ring Buffers

    Daily Temperatures: How to use an Index-Tracking Monotonic Stack for next warmer day in O(N)

    Abhay Tiwari
    Abhay Tiwari Begginer
    Added an answer on September 11, 2026 at 9:54 am

    This problem is the cleanest introductory template for the Monotonic Decreasing Stack pattern. Let's look at why storing indices unlocks the distance calculation. 1. The Mental Model Imagine people waiting in line holding temperature tickets. If temperatures are dropping: [73, 71, 69], nobody has foRead more

    This problem is the cleanest introductory template for the Monotonic Decreasing Stack pattern. Let’s look at why storing indices unlocks the distance calculation.

    1. The Mental Model

    Imagine people waiting in line holding temperature tickets. If temperatures are dropping: [73, 71, 69], nobody has found a warmer day yet! So everyone has to stay waiting in line.

    Now, a warm day arrives: 72!

    • The person holding 69 sees 72 > 69. Their wait is over! They step out of line.
    • The person holding 71 sees 72 > 71. Their wait is over! They step out of line.
    • The person holding 73 sees 72 < 73. 72 is not warm enough for them! The person with 73 stays waiting in line, and the day with 72 joins the line behind them.

    2. Why Store Indices Instead of Values?

    If you only push temperature numbers (e.g. 69) onto the stack, when a warmer day 72 pops 69, you know that a warmer day happened, but you don’t know how many days elapsed!

    By pushing the array index prev_day onto the stack:

    days_waited = current_day - prev_day
    answer[prev_day] = days_waited
    

    You calculate the exact time difference in $O(1)$ and write directly to the output array!


    Clean Python 3.12 Implementation

    def daily_temperatures(temperatures: list[int]) -> list[int]:
        """Finds wait time until warmer day in O(N) time and O(N) auxiliary space."""
        n = len(temperatures)
        ans = [0] * n
        stack: list[int] = [] # Stores indices of previous cooler days
    
        for curr_day, temp in enumerate(temperatures):
            # Pop all previous days that are strictly cooler than today
            while stack and temperatures[stack[-1]] < temp:
                prev_day = stack.pop()
                ans[prev_day] = curr_day - prev_day
    
            stack.append(curr_day)
    
        return ans
    

    Complexity Breakdown

    • Time Complexity: O(N). Every index is pushed onto the stack once and popped at most once. Total operations: $le 2N$.
    • Space Complexity: O(N) for the stack in the worst-case of strictly decreasing temperatures (e.g. [100, 90, 80, 70]).
    See less
    • 0
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
  7. Asked: September 11, 2026In: Data Structures & Algorithms, Trees, BSTs & Hierarchical Indexes

    Lowest Common Ancestor: Why Binary Lifting in O(log N) beats naive DFS in high-scale DAGs

    Anonymous
    Anonymous Begginer
    Added an answer on September 11, 2026 at 9:54 am

    When you have multiple online LCA queries on a static tree, the gold standard is Binary Lifting (used in compiler dominance frontiers, distributed network routing, and Git commit histories). 1. The Core Idea: Powers of 2 Parent Jumps Instead of storing only a node's immediate parent (which forces yoRead more

    When you have multiple online LCA queries on a static tree, the gold standard is Binary Lifting (used in compiler dominance frontiers, distributed network routing, and Git commit histories).

    1. The Core Idea: Powers of 2 Parent Jumps

    Instead of storing only a node’s immediate parent (which forces you to step up the tree one node at a time in $O(N)$), what if every node stored its ancestor at distance $2^0, 2^1, 2^2, 2^3, dots, 2^k$?

    We define a 2D table: up[u][i] = the (2^i)-th ancestor of node u.

    The state transition is pure dynamic programming:

    up[u][i] = up[ up[u][i-1] ][i-1]
    

    In English: ‘To jump $2^i$ steps up from $u$, first jump $2^{i-1}$ steps up to reach intermediate node $v$, and then from $v$ jump another $2^{i-1}$ steps!’ ($2^{i-1} + 2^{i-1} = 2^i$).


    2. Answering an LCA Query in 2 Steps

    To find the LCA of nodes u and v:

    1. Level the Depths: If depth[u] < depth[v], swap them. Use binary powers to jump u upwards until depth[u] == depth[v] in $O(log N)$ steps. If u == v, they were on the same branch → return u!
    2. Simultaneous Binary Leap: Jump both u and v upwards together using the largest possible power of 2 such that their ancestors are still different (up[u][i] != up[v][i]). When no more jumps can be made, their immediate parent (up[u][0]) is their Lowest Common Ancestor!

    Clean C++20 Implementation

    #include <vector>
    #include <cmath>
    #include <algorithm>
    
    class TreeLCA {
        int n, max_log;
        std::vector<int> depth;
        std::vector<std::vector<int>> up;
    
        void dfs(int u, int p, int d, const std::vector<std::vector<int>>& adj) {
            depth[u] = d;
            up[u][0] = p;
            for (int i = 1; i < max_log; ++i) {
                up[u][i] = up[ up[u][i - 1] ][i - 1];
            }
            for (int v : adj[u]) {
                if (v != p) {
                    dfs(v, u, d + 1, adj);
                }
            }
        }
    
    public:
        TreeLCA(int nodes, int root, const std::vector<std::vector<int>>& adj) : n(nodes) {
            max_log = std::ceil(std::log2(n)) + 1;
            depth.assign(n, 0);
            up.assign(n, std::vector<int>(max_log, root));
            dfs(root, root, 0, adj);
        }
    
        int queryLCA(int u, int v) {
            if (depth[u] < depth[v]) std::swap(u, v);
    
            // Step 1: Bring u and v to same depth
            int diff = depth[u] - depth[v];
            for (int i = 0; i < max_log; ++i) {
                if ((diff >> i) & 1) {
                    u = up[u][i];
                }
            }
            if (u == v) return u;
    
            // Step 2: Jump together
            for (int i = max_log - 1; i >= 0; --i) {
                if (up[u][i] != up[v][i]) {
                    u = up[u][i];
                    v = up[v][i];
                }
            }
            return up[u][0];
        }
    };
    

    Complexity Breakdown

    • Preprocessing Time: O(N log N) via a single DFS pass.
    • Preprocessing Memory: O(N log N) to store the jump table.
    • Per Query Time: Strictly O(log N). For $N = 1,000,000$, $log_2(1,000,000) pprox 20$ operations. You can evaluate 50,000 queries in a fraction of a second!
    See less
    • 0
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
  8. Asked: September 11, 2026In: Data Structures & Algorithms, Hashing & Collision Resolution

    Subarray Sum Equals K: Why Two Pointers fails with negative numbers and Hash Map is mandatory

    Abhay Tiwari
    Abhay Tiwari Begginer
    Added an answer on September 11, 2026 at 9:53 am

    This is a classic trap that catches even intermediate developers. Let's see why two pointers collapse and why prefix math is the ultimate solution. 1. Why Two Pointers Fails on Negative Numbers A sliding window relies on a fundamental monotonic invariant: If the current sum is too small, expanding tRead more

    This is a classic trap that catches even intermediate developers. Let’s see why two pointers collapse and why prefix math is the ultimate solution.

    1. Why Two Pointers Fails on Negative Numbers

    A sliding window relies on a fundamental monotonic invariant:

    • If the current sum is too small, expanding the right pointer will increase the sum.
    • If the current sum is too large, contracting the left pointer will decrease the sum.

    The moment you introduce negative numbers, this invariant is destroyed! Expanding the right pointer might add -10, making the sum smaller. Shrinking the left pointer might drop -5, making the sum larger. You can no longer make greedy left/right decisions!


    2. The Prefix Sum Invariant

    Let prefix[i] be the cumulative sum from index 0 to i.

    The sum of any contiguous subarray from index j + 1 to i is given by: sum(j+1 ... i) = prefix[i] - prefix[j].

    We want this subarray sum to equal k:

    prefix[i] - prefix[j] = k
    prefix[j] = prefix[i] - k
    

    The Breakthrough: As you iterate through the array maintaining a running prefix sum curr_sum, you simply ask the hash map: ‘How many times have we already seen a prefix sum equal to curr_sum - k in the past?’

    Every time you find that value in the hash map, you have found a valid subarray that sums exactly to k!


    Clean Python 3.12 Implementation

    from collections import defaultdict
    
    def subarray_sum(nums: list[int], k: int) -> int:
        """Counts subarrays summing to k in O(N) time and O(N) space."""
        # Base case: A prefix sum of 0 has occurred once (an empty prefix)
        prefix_counts: dict[int, int] = defaultdict(int)
        prefix_counts[0] = 1
    
        curr_sum = 0
        total_subarrays = 0
    
        for x in nums:
            curr_sum += x
            target = curr_sum - k
            
            # Add all occurrences of the complementary prefix sum
            if target in prefix_counts:
                total_subarrays += prefix_counts[target]
                
            # Record current prefix sum
            prefix_counts[curr_sum] += 1
    
        return total_subarrays
    

    Why prefix_counts[0] = 1 is Critical

    If you forget prefix_counts[0] = 1, any subarray that starts at index 0 and sums to k (e.g. nums = [3, ...], k = 3) will produce curr_sum = 3, and look for curr_sum - k = 0 in the map. Without the base case, it would fail to count that valid subarray!


    Complexity Breakdown

    • Time Complexity: O(N). Single pass through the array with O(1) hash map lookups.
    • Space Complexity: O(N) to store prefix sum frequencies.
    See less
    • 0
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
  9. Asked: September 11, 2026In: Data Structures & Algorithms, Two Pointers & Sliding Window

    Minimum Window Substring: Why an integer frequency array beats HashMap in low-latency parsers

    Abhay Tiwari
    Abhay Tiwari Begginer
    Added an answer on September 11, 2026 at 9:53 am

    Minimum Window Substring is the crown jewel of sliding window problems. The difference between a junior solution and a staff engineer solution comes down to how window validation is tracked. 1. The Trap: Comparing Two Hash Maps In naive implementations, developers maintain two hash maps: target_counRead more

    Minimum Window Substring is the crown jewel of sliding window problems. The difference between a junior solution and a staff engineer solution comes down to how window validation is tracked.

    1. The Trap: Comparing Two Hash Maps

    In naive implementations, developers maintain two hash maps: target_counts and window_counts. Whenever the window slides, they loop through the keys of target_counts to see if the window is valid. That turns an $O(N)$ algorithm into $O(N cdot |Sigma|)$ with heavy hash table overhead!


    2. The Staff Engineer Pattern: Single Vector + Deficit Counter

    We can optimize this down to bare metal with two simple tricks:

    1. Fixed 128-integer Array: Standard ASCII fits inside 128 indices. An array of 128 integers takes 512 bytes, fitting completely inside an L1 data cache line.
    2. A Single Deficit Counter (required): We set required = len(t). When expanding the window with pointer r, if counts[s[r]] > 0, that character was actively needed, so we decrement required--. When required == 0, the window is 100% valid! We don’t have to check any other variables!

    Clean Python 3.12 Implementation

    def min_window(s: str, t: str) -> str:
        """Finds minimum window substring in strict O(|s| + |t|) time and O(1) space."""
        if not s or not t or len(s) < len(t):
            return ""
    
        # Frequency map using fixed 128 ASCII array
        freq = [0] * 128
        for char in t:
            freq[ord(char)] += 1
    
        required = len(t)
        min_len = float('inf')
        start_idx = 0
        left = 0
    
        for right in range(len(s)):
            r_char = ord(s[right])
            
            # If this character was still needed by t
            if freq[r_char] > 0:
                required -= 1
                
            freq[r_char] -= 1
    
            # While window satisfies all characters in t -> contract left boundary
            while required == 0:
                window_len = right - left + 1
                if window_len < min_len:
                    min_len = window_len
                    start_idx = left
    
                l_char = ord(s[left])
                freq[l_char] += 1
                
                # If removing this character breaks the required quota
                if freq[l_char] > 0:
                    required += 1
                    
                left += 1
    
        return "" if min_len == float('inf') else s[start_idx : start_idx + min_len]
    

    Complexity Breakdown

    • Time Complexity: O(|s| + |t|). The right pointer advances |s| times. The left pointer advances at most |s| times. Total pointer advances = 2|s|.
    • Space Complexity: O(1) auxiliary space. Exactly 128 integers on the stack.
    See less
    • 0
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
  10. Asked: September 11, 2026In: Bit Manipulation & Low-Level Computing, Data Structures & Algorithms

    How to find the Single Number when all others appear 3 times using a Digital Logic State Machine?

    Abhay Tiwari
    Abhay Tiwari Begginer
    Added an answer on September 11, 2026 at 9:53 am

    This problem is a masterpiece of digital circuit design translated into software code. Let's design the state machine from first principles. 1. The Three States of a Bit For any bit position, as we scan numbers in the array, how many times can we see a 1? Seen 0 times → Count = 0 Seen 1 timeRead more

    This problem is a masterpiece of digital circuit design translated into software code. Let’s design the state machine from first principles.

    1. The Three States of a Bit

    For any bit position, as we scan numbers in the array, how many times can we see a 1?

    • Seen 0 times → Count = 0
    • Seen 1 time → Count = 1
    • Seen 2 times → Count = 2
    • Seen 3 times → Resets back to 0!

    To represent 3 distinct states (0, 1, and 2), we need 2 bits of memory! Let’s name them:

    • twos (the high bit)
    • ones (the low bit)

    2. The Truth Table

    When a new bit x arrives from the current number:

    Current State (twos, ones)Input Bit (x)Next State (twos, ones)Explanation
    0, 000, 0Seen 0 times
    0, 010, 1Seen 1 time
    0, 100, 1Unchanged
    0, 111, 0Seen 2 times
    1, 001, 0Unchanged
    1, 010, 0Seen 3 times → RESETS TO 0!

    3. Deriving the Logic Gates

    From the truth table:

    • ones = (ones ^ x) & (~twos)
    • twos = (twos ^ x) & (~ones)

    When the full array has been scanned:

    • Every element that appeared 3 times completed the full cycle $(0 o 1 o 2 o 0)$ and returned both bits to 0.
    • The single element that appeared 1 time transitioned from $0 o 1$. Its bits are left recorded inside ones!

    Clean Python 3.12 Implementation

    def single_number(nums: list[int]) -> int:
        """Finds element appearing once while others appear 3 times in O(N) time and O(1) space."""
        ones = 0
        twos = 0
    
        for x in nums:
            # Update ones: XOR with x, but clear if twos already holds this bit
            ones = (ones ^ x) & ~twos
            # Update twos: XOR with x, but clear if ones now holds this bit
            twos = (twos ^ x) & ~ones
    
        return ones
    

    Complexity Breakdown

    • Time Complexity: O(N). We touch each number once with 4 single-cycle bitwise operations.
    • Space Complexity: O(1). Exactly two integer variables living in registers.
    See less
    • 0
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
Load More Answers

Sidebar

Ask A Question
  • Popular
  • Answers
  • Queryiest

    What is a database?

    • 3 Answers
  • Anonymous

    How to rotate an array in-place with O(1) space and ...

    • 3 Answers
  • hannah

    What steps can businesses take to identify the most valuable ...

    • 2 Answers
  • Vikram
    aarav0 added an answer Direct Technical Solution: Unlike IVFFlat (which partitions vector spaces with… September 11, 2026 at 9:57 pm
  • Abhishek
    Abhishek added an answer Direct Technical Solution: In C++20, range view adaptors (like std::views::filter,… September 11, 2026 at 9:57 pm
  • Sneha Patel
    Anonymous added an answer Direct Technical Solution: torch.cuda.empty_cache() releases only cached (unallocated) blocks back… September 11, 2026 at 9:57 pm

Top Members

Queryiest

Queryiest

  • 201 Questions
  • 295 Points
Enlightened
Anonymous

Anonymous

  • 11 Questions
  • 42 Points
Begginer
paperubofficial

paperubofficial

  • 0 Questions
  • 22 Points
Begginer

Trending Tags

ai asp.net aws basics aws certification aws console aws free tier aws login aws scenario-based questions c++ career cyber security cyber security interview git java javascript jobs jquery net core net core interview questions sql

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • DSA Problems
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • New Questions
  • Trending Questions
  • Must read Questions
  • Hot Questions

Footer

About Us

  • Meet The Team
  • Blog
  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy
  • Disclaimer
  • Terms & Conditions

Help

  • Knowledge Base
  • Support

Follow

© 2023-25 RTSALL. All Rights Reserved