InterviewPitch
C# Interview Questions

C# Interview Questions with Answers

Most Asked C# Interview Questions for Software Engineer Roles

100+ QuestionsDetailed AnswersCode ExamplesUpdated for 2026

Introduction

This page provides a comprehensive collection of C# Interview Questions and Answers to help students, fresh graduates, and experienced .NET developers prepare for technical interviews. The questions range from basic C# programming concepts to advanced .NET application development topics frequently asked by top software companies. C# is one of the most popular object-oriented programming languages developed by Microsoft and is widely used for building desktop applications, web applications, enterprise software, cloud services, APIs, mobile apps, and games using the .NET platform. This interview guide includes beginner, intermediate, advanced, and scenario-based C# interview questions covering OOP concepts, collections, delegates, events, LINQ, asynchronous programming, multithreading, exception handling, memory management, ASP.NET Core, Entity Framework, and modern C# language features.

Why C#?

  • Cross-platform development with .NET Core / .NET 5+
  • Rich ecosystem with powerful libraries and frameworks (ASP.NET Core, Entity Framework, etc.)
  • Automatic memory management with garbage collection
  • Enterprise-grade, widely used in desktop, web, cloud, and game development
  • Massive community support and highly in-demand for technical interviews

Most Asked C# Interview Questions

Beginner
1. What is C# and what are its key features?

C# is a modern, object-oriented programming language developed by Microsoft as part of the .NET platform. It combines the power of C++ with the simplicity of Java and adds modern features like LINQ and async/await.

  • Object-Oriented: Classes, inheritance, polymorphism, encapsulation
  • Type-Safe: Strong typing with type inference via var
  • LINQ: Language Integrated Query for data manipulation
  • Async/Await: Simplified asynchronous programming
  • Garbage Collection: Automatic memory management
csharp
// Hello World in C#
using System;

class Program {
    static void Main() {
        Console.WriteLine("Hello, World!");
    }
}
Beginner
2. What are Data Types in C#?

C# provides both value types (structs) and reference types (classes). The language includes built-in types and supports user-defined types.

  • int — 32-bit integer
  • float — 32-bit floating point (must use f suffix)
  • double — 64-bit floating point
  • decimal — 128-bit precision for financial calculations
  • char — 16-bit Unicode character
  • bool — true/false
  • string — immutable sequence of characters
csharp
// Data Types in C#
using System;

class Program {
    static void Main() {
        int age = 25;
        float salary = 50000.50f;
        double pi = 3.14159265358979;
        char grade = 'A';
        bool isActive = true;
        string name = "Alice";
        decimal price = 99.99m;

        Console.WriteLine($"Age: {age}");
        Console.WriteLine($"Salary: {salary}");
        Console.WriteLine($"Pi: {pi}");
        Console.WriteLine($"Grade: {grade}");
        Console.WriteLine($"Active: {isActive}");
        Console.WriteLine($"Name: {name}");
        Console.WriteLine($"Price: {price}");
    }
}
Beginner
3. What are Variables, Constants, and Readonly in C#?

C# uses const for compile-time constants, readonly for runtime constants that can be set in the constructor, and var for type inference.

  • const — compile-time constant, must be initialized
  • readonly — runtime constant, can be set in constructor
  • var — compiler infers type from initialization
  • dynamic — bypasses compile-time type checking
csharp
// Variables, Constants, and Readonly
using System;

class Program {
    const double PI = 3.14159;
    readonly int MAX = 100;

    static void Main() {
        int x = 10;
        const int MIN_VALUE = 0;
        
        // var type inference
        var val = 3.14;
        var str = "Hello";
        
        Console.WriteLine($"x = {x}");
        Console.WriteLine($"PI = {PI}");
        Console.WriteLine($"val = {val}");
        Console.WriteLine($"str = {str}");
    }
}
Beginner
4. How do Classes and Objects work in C#?

A class is a blueprint that encapsulates data and behavior. C# uses properties for clean access control, constructors for initialization, and finalizers for cleanup.

  • private — accessible only within the class
  • public — accessible from anywhere
  • protected — accessible in derived classes
  • Properties provide getters and setters
  • Finalizer ~ClassName() (called by garbage collector)
csharp
// OOP - Classes and Objects
using System;

class Car {
    private string brand;
    private int year;
    private double price;

    // Constructor
    public Car(string brand, int year, double price) {
        this.brand = brand;
        this.year = year;
        this.price = price;
    }

    // Properties
    public string Brand { get { return brand; } }
    public int Year { get { return year; } }
    public double Price { get { return price; } }

    // Method
    public void Display() {
        Console.WriteLine("Brand: " + brand + ", Year: " + year + ", Price: $" + price);
    }

    // Destructor (Finalizer)
    ~Car() {
        Console.WriteLine(brand + " destroyed.");
    }
}

class Program {
    static void Main() {
        Car c1 = new Car("Toyota", 2022, 25000.0);
        Car c2 = new Car("BMW", 2023, 55000.0);

        c1.Display();
        c2.Display();
        Console.WriteLine("Brand: " + c1.Brand);
    }
}
Beginner
5. What are Constructors and Finalizers in C#?

A constructor initializes an object when it is created. C# supports default, parameterized, and copy constructors via the this keyword. Finalizers (destructors) are called by the garbage collector.

  • Default constructor — no parameters
  • Parameterized constructor — accepts arguments
  • Constructor chaining with this keyword
  • Finalizer syntax: ~ClassName()
  • Use IDisposable for deterministic cleanup
csharp
// Constructors and Destructors
using System;

class Student {
    private string name;
    private int age;

    // Default constructor
    public Student() : this("Unknown", 0) {
        Console.WriteLine("Default constructor called");
    }

    // Parameterized constructor
    public Student(string name, int age) {
        this.name = name;
        this.age = age;
        Console.WriteLine($"Parameterized constructor: {name}");
    }

    // Copy constructor
    public Student(Student other) {
        this.name = other.name;
        this.age = other.age;
        Console.WriteLine($"Copy constructor: {name}");
    }

    public void Display() {
        Console.WriteLine($"Name: {name}, Age: {age}");
    }

    ~Student() {
        Console.WriteLine($"Destructor: {name}");
    }
}

class Program {
    static void Main() {
        Student s1 = new Student();
        Student s2 = new Student("Alice", 20);
        Student s3 = new Student(s2);  // copy constructor

        s1.Display();
        s2.Display();
        s3.Display();
    }
}
Intermediate
6. How does Inheritance work in C#?

Inheritance in C# uses the : syntax and supports single inheritance (one base class) plus multiple interface implementation.

  • sealed — prevents further inheritance
  • abstract — cannot be instantiated
  • virtual — allows overriding in derived classes
  • override — overrides a virtual method
  • base — calls base class constructor/method
csharp
// Inheritance in C#
using System;

class Animal {
    protected string name;
    protected int age;

    public Animal(string name, int age) {
        this.name = name;
        this.age = age;
    }

    public virtual void Speak() {
        Console.WriteLine($"{name} makes a sound.");
    }

    public void Info() {
        Console.WriteLine($"Name: {name}, Age: {age}");
    }
}

class Dog : Animal {
    private string breed;

    public Dog(string name, int age, string breed) : base(name, age) {
        this.breed = breed;
    }

    public override void Speak() {
        Console.WriteLine($"{name} says: Woof!");
    }

    public void Display() {
        Info();
        Console.WriteLine($"Breed: {breed}");
    }
}

class Cat : Animal {
    public Cat(string name, int age) : base(name, age) { }

    public override void Speak() {
        Console.WriteLine($"{name} says: Meow!");
    }
}

class Program {
    static void Main() {
        Dog dog = new Dog("Rex", 3, "German Shepherd");
        Cat cat = new Cat("Whiskers", 2);

        dog.Display();
        dog.Speak();
        cat.Speak();

        // Polymorphism via base reference
        Animal a = dog;
        a.Speak();
    }
}
Intermediate
7. What is Polymorphism in C#?

Polymorphism allows objects of different classes to be treated through a common base class or interface. Abstract classes define contracts that derived classes must implement.

  • abstract class — cannot be instantiated
  • abstract method — no implementation, must be overridden
  • virtual + override — runtime polymorphism
  • Interface — pure contract with no implementation
csharp
// Polymorphism and Abstract Classes
using System;

abstract class Shape {
    public abstract double Area();
    public abstract double Perimeter();

    public void Display() {
        Console.WriteLine($"Area: {Area()}, Perimeter: {Perimeter()}");
    }
}

class Circle : Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    public override double Area() {
        return Math.PI * radius * radius;
    }

    public override double Perimeter() {
        return 2 * Math.PI * radius;
    }
}

class Rectangle : Shape {
    private double width, height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    public override double Area() {
        return width * height;
    }

    public override double Perimeter() {
        return 2 * (width + height);
    }
}

class Program {
    static void Main() {
        Shape[] shapes = {
            new Circle(5.0),
            new Rectangle(4.0, 6.0)
        };

        foreach (var s in shapes) {
            s.Display();
        }
    }
}
Intermediate
8. What is Operator Overloading in C#?

Operator overloading allows custom behavior for operators (+, -, ==, etc.) on user-defined types, making them more intuitive to use.

  • Must be public static methods
  • Operators: +, -, *, /, ==, !=, <, >
  • Unary operators: ++, --, !
  • Override Equals() and GetHashCode() when overloading ==
csharp
// Operator Overloading
using System;

class Vector2D {
    public double X { get; set; }
    public double Y { get; set; }

    public Vector2D(double x = 0, double y = 0) {
        X = x; Y = y;
    }

    // + operator
    public static Vector2D operator +(Vector2D a, Vector2D b) {
        return new Vector2D(a.X + b.X, a.Y + b.Y);
    }

    // - operator
    public static Vector2D operator -(Vector2D a, Vector2D b) {
        return new Vector2D(a.X - b.X, a.Y - b.Y);
    }

    // * scalar
    public static Vector2D operator *(Vector2D v, double s) {
        return new Vector2D(v.X * s, v.Y * s);
    }

    // == operator
    public static bool operator ==(Vector2D a, Vector2D b) {
        if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
            return ReferenceEquals(a, b);
        return a.X == b.X && a.Y == b.Y;
    }

    public static bool operator !=(Vector2D a, Vector2D b) {
        return !(a == b);
    }

    public override string ToString() {
        return $"({X}, {Y})";
    }
}

class Program {
    static void Main() {
        Vector2D v1 = new Vector2D(3, 4);
        Vector2D v2 = new Vector2D(1, 2);
        
        Console.WriteLine($"v1 = {v1}");
        Console.WriteLine($"v2 = {v2}");
        Console.WriteLine($"v1 + v2 = {v1 + v2}");
        Console.WriteLine($"v1 - v2 = {v1 - v2}");
        Console.WriteLine($"v1 * 2 = {v1 * 2}");
        Console.WriteLine($"v1 == v2: {v1 == v2}");
    }
}
Intermediate
9. What are Generics in C#?

Generics enable type-safe code that works with any type without boxing or casting. They are resolved at compile time, providing performance and type safety.

  • Generic classes — class Stack<T>
  • Generic methods — T Max<T>(T a, T b) where T : IComparable
  • Constraints — where T : class, new()
  • Multiple type parameters — class Pair<K, V>
csharp
// Generics in C#
using System;

// Generic class
class Stack<T> {
    private T[] data = new T[100];
    private int top = -1;

    public void Push(T val) {
        data[++top] = val;
    }

    public T Pop() {
        return data[top--];
    }

    public T Peek() {
        return data[top];
    }

    public bool IsEmpty() {
        return top == -1;
    }
}

// Generic method
class Program {
    static T Max<T>(T a, T b) where T : IComparable<T> {
        return a.CompareTo(b) > 0 ? a : b;
    }

    static void Swap<T>(ref T a, ref T b) {
        T temp = a;
        a = b;
        b = temp;
    }

    // Multiple type parameters
    class Pair<K, V> {
        public K Key { get; set; }
        public V Value { get; set; }

        public Pair(K key, V value) {
            Key = key;
            Value = value;
        }

        public void Print() {
            Console.WriteLine($"{Key} -> {Value}");
        }
    }

    static void Main() {
        Console.WriteLine(Max(10, 20));
        Console.WriteLine(Max(3.5, 2.1));
        Console.WriteLine(Max("B", "A"));

        Stack<int> si = new Stack<int>();
        si.Push(1); si.Push(2); si.Push(3);
        Console.WriteLine($"{si.Pop()} {si.Pop()}");

        Pair<string, int> p = new Pair<string, int>("age", 25);
        p.Print();
    }
}
Intermediate
10. How do Collections - Lists work in C#?

A List<T> is a dynamic array from the System.Collections.Generic namespace. It provides O(1) random access and integrates with LINQ for powerful data queries.

  • Add() — add to end
  • Insert() — add at position O(n)
  • Remove() — remove element
  • Sort() — sort in place
  • LINQ: Where(), Select(), OrderBy()
csharp
// Collections - Lists
using System;
using System.Collections.Generic;
using System.Linq;

class Program {
    static void Main() {
        List<int> list = new List<int> { 5, 2, 8, 1, 9, 3 };

        // Add elements
        list.Add(7);
        list.Insert(0, 0);

        // Count and capacity
        Console.WriteLine($"Count: {list.Count}");
        Console.WriteLine($"Capacity: {list.Capacity}");

        // Iterate
        foreach (int x in list) Console.Write($"{x} ");
        Console.WriteLine();

        // Sort
        list.Sort();
        foreach (int x in list) Console.Write($"{x} ");
        Console.WriteLine();

        // Find and remove
        list.Remove(8);

        // 2D List
        List<List<int>> mat = new List<List<int>>();
        for (int i = 0; i < 3; i++) {
            mat.Add(new List<int>(new int[3]));
        }
        mat[1][1] = 5;
        Console.WriteLine($"mat[1][1] = {mat[1][1]}");

        // LINQ
        var evens = list.Where(x => x % 2 == 0).ToList();
        Console.WriteLine("Evens: " + string.Join(", ", evens));
    }
}
Intermediate
11. How do Dictionary and HashSet work in C#?

Dictionary<TKey, TValue> is a hash-based key-value store with O(1) average operations. HashSet<T> stores unique elements with O(1) lookups.

  • Dictionary — key-value pairs, O(1) average
  • HashSet — unique elements, O(1) average
  • SortedDictionary — ordered by key
  • TryGetValue() — safe lookup without exception
csharp
// Dictionary and HashSet
using System;
using System.Collections.Generic;
using System.Linq;

class Program {
    static void Main() {
        // Dictionary (HashMap)
        Dictionary<string, int> scores = new Dictionary<string, int>();
        scores["Alice"] = 95;
        scores["Bob"] = 87;
        scores["Carol"] = 92;

        foreach (var kvp in scores) {
            Console.WriteLine($"{kvp.Key}: {kvp.Value}");
        }

        Console.WriteLine($"Alice: {scores["Alice"]}");
        Console.WriteLine($"Contains Bob: {scores.ContainsKey("Bob")}");

        // HashSet
        HashSet<int> set = new HashSet<int> { 5, 2, 8, 2, 1, 9, 5 };
        foreach (int x in set) Console.Write($"{x} ");
        Console.WriteLine();

        set.Add(6);
        set.Remove(2);
        Console.WriteLine($"Contains 5: {set.Contains(5)}");

        // SortedDictionary
        SortedDictionary<string, int> sorted = new SortedDictionary<string, int>();
        sorted["banana"] = 3;
        sorted["apple"] = 5;
        sorted["cherry"] = 2;
        foreach (var kvp in sorted) {
            Console.WriteLine($"{kvp.Key}: {kvp.Value}");
        }
    }
}
Intermediate
12. How do Stack, Queue, and PriorityQueue work in C#?

C# provides Stack (LIFO), Queue (FIFO), and PriorityQueue (ordered by priority) as part of System.Collections.Generic.

  • Stack: Push(), Pop(), Peek()
  • Queue: Enqueue(), Dequeue(), Peek()
  • PriorityQueue: Enqueue(item, priority), Dequeue()
  • LinkedList — doubly-linked list
csharp
// Stack, Queue, and PriorityQueue
using System;
using System.Collections.Generic;

class Program {
    static void Main() {
        // Stack (LIFO)
        Stack<int> stack = new Stack<int>();
        stack.Push(10);
        stack.Push(20);
        stack.Push(30);
        Console.WriteLine($"Stack top: {stack.Peek()}");
        while (stack.Count > 0) {
            Console.Write($"{stack.Pop()} ");
        }
        Console.WriteLine();

        // Queue (FIFO)
        Queue<int> queue = new Queue<int>();
        queue.Enqueue(10);
        queue.Enqueue(20);
        queue.Enqueue(30);
        Console.WriteLine($"Queue front: {queue.Peek()}");
        while (queue.Count > 0) {
            Console.Write($"{queue.Dequeue()} ");
        }
        Console.WriteLine();

        // PriorityQueue (.NET 6+)
        PriorityQueue<string, int> pq = new PriorityQueue<string, int>();
        pq.Enqueue("Low", 3);
        pq.Enqueue("High", 1);
        pq.Enqueue("Medium", 2);
        while (pq.Count > 0) {
            var item = pq.Dequeue();
            Console.Write($"{item} ");
        }
        Console.WriteLine();

        // LinkedList (Doubly-linked)
        LinkedList<int> ll = new LinkedList<int>();
        ll.AddLast(10);
        ll.AddLast(20);
        ll.AddFirst(5);
        foreach (int x in ll) Console.Write($"{x} ");
        Console.WriteLine();
    }
}
Intermediate
13. How does Exception Handling work in C#?

Exception handling uses try, catch, finally, and throw keywords. Custom exceptions inherit from Exception or ApplicationException.

  • throw — raises an exception
  • catch — handles specific exception types
  • finally — always executes (cleanup)
  • Custom exceptions — inherit from Exception
csharp
// Exception Handling
using System;

// Custom exception
class ValidationError : Exception {
    public int Code { get; }

    public ValidationError(string message, int code) : base(message) {
        Code = code;
    }
}

class Program {
    static double Divide(double a, double b) {
        if (b == 0) throw new ArgumentException("Division by zero!");
        return a / b;
    }

    static int GetAge(int age) {
        if (age < 0 || age > 150)
            throw new ValidationError($"Invalid age: {age}", 400);
        return age;
    }

    static void Main() {
        // Basic try-catch
        try {
            Console.WriteLine(Divide(10, 2));
            Console.WriteLine(Divide(10, 0));  // throws
        } catch (ArgumentException e) {
            Console.WriteLine($"Error: {e.Message}");
        }

        // Custom exception
        try {
            GetAge(200);
        } catch (ValidationError e) {
            Console.WriteLine($"Validation [{e.Code}]: {e.Message}");
        } catch (Exception e) {
            Console.WriteLine($"General: {e.Message}");
        }

        // Finally block
        try {
            Console.WriteLine("Processing...");
        } finally {
            Console.WriteLine("Cleanup always runs");
        }
    }
}
Advanced
14. What is IDisposable and the Using Statement in C#?

IDisposable provides deterministic resource cleanup. The using statement ensures Dispose() is called even when exceptions occur, following the RAII pattern.

  • IDisposable — implement for resource cleanup
  • using statement — automatic disposal
  • using declaration (C# 8+) — scoped disposal
  • Used for file handles, database connections, mutexes
csharp
// IDisposable and Using Statement
using System;

class Resource : IDisposable {
    private string name;

    public Resource(string name) {
        this.name = name;
        Console.WriteLine($"Resource acquired: {name}");
    }

    public void Use() {
        Console.WriteLine($"Using: {name}");
    }

    public void Dispose() {
        Console.WriteLine($"Resource released: {name}");
    }
}

class Program {
    static void Main() {
        // Using statement (auto-dispose)
        using (Resource r1 = new Resource("FileResource")) {
            r1.Use();
        }  // Auto-disposed here

        // Using declaration (C# 8+)
        using Resource r2 = new Resource("DatabaseResource");
        r2.Use();
        // Auto-disposed at end of scope

        // Try-finally equivalent
        Resource r3 = null;
        try {
            r3 = new Resource("NetworkResource");
            r3.Use();
        } finally {
            r3?.Dispose();
        }
    }
}
Advanced
15. What are Lambda Expressions and LINQ in C#?

Lambda expressions (() => {}) are anonymous functions used extensively with LINQ for data querying. Func and Action delegates handle lambda storage.

  • Func<T, R> — delegate with return value
  • Action<T> — delegate without return value
  • LINQ: Where(), Select(), OrderBy(), Aggregate()
  • Closures capture variables from enclosing scope
csharp
// Lambda Expressions and LINQ
using System;
using System.Collections.Generic;
using System.Linq;

class Program {
    static void Main() {
        // Basic lambda
        Action<string> greet = (name) => {
            Console.WriteLine($"Hello, {name}!");
        };
        greet("Alice");

        // Func delegate
        Func<int, int, int> add = (x, y) => x + y;
        Console.WriteLine($"Add: {add(10, 20)}");

        // Lambda with closures
        int x = 10;
        Func<int> addX = () => x + 5;
        Console.WriteLine($"addX: {addX()}");

        // LINQ with lambda
        List<int> nums = new List<int> { 5, 1, 8, 3, 9, 2, 7 };
        
        // Sort
        nums.Sort((a, b) => a.CompareTo(b));
        Console.WriteLine(string.Join(" ", nums));

        // Filter
        var evens = nums.Where(n => n % 2 == 0).ToList();
        Console.WriteLine($"Evens: {string.Join(" ", evens)}");

        // Transform
        var squares = nums.Select(n => n * n).ToList();
        Console.WriteLine($"Squares: {string.Join(" ", squares)}");

        // Aggregate
        int sum = nums.Aggregate(0, (acc, n) => acc + n);
        Console.WriteLine($"Sum: {sum}");

        // Action and Func delegates
        Action<int> print = n => Console.Write($"{n} ");
        Func<int, int> doubleIt = n => n * 2;
    }
}
Advanced
16. How does Async/Await work in C#?

Async/Await (C# 5) enables non-blocking asynchronous programming using Task and Task<T>. The compiler transforms async methods into state machines.

  • async — marks a method as asynchronous
  • await — suspends execution until task completes
  • Task.WhenAll() — wait for multiple tasks
  • Task.Run() — run CPU-bound work on thread pool
csharp
// Async/Await and Tasks
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;

class Program {
    static async Task<string> FetchDataAsync(string url, int delay) {
        await Task.Delay(delay);
        return $"Data from {url}";
    }

    static async Task<int> ComputeAsync(int a, int b) {
        await Task.Delay(100);
        return a + b;
    }

    static async Task Main() {
        // Basic async
        string result = await FetchDataAsync("api.example.com", 500);
        Console.WriteLine(result);

        // Parallel async tasks
        var tasks = new List<Task<string>> {
            FetchDataAsync("source1", 300),
            FetchDataAsync("source2", 200),
            FetchDataAsync("source3", 400)
        };
        string[] results = await Task.WhenAll(tasks);
        Console.WriteLine("All results: " + string.Join(", ", results));

        // Task with exception handling
        try {
            await Task.Run(() => {
                throw new InvalidOperationException("Task failed");
            });
        } catch (Exception e) {
            Console.WriteLine($"Caught: {e.Message}");
        }

        // Parallel processing
        var numbers = Enumerable.Range(1, 10).ToList();
        var parallelResults = await Task.WhenAll(
            numbers.Select(async n => {
                await Task.Delay(50);
                return n * n;
            })
        );
        Console.WriteLine($"Squares: {string.Join(", ", parallelResults)}");
    }
}
Intermediate
17. How does File I/O work in C#?

C# provides File and FileInfo for static operations, and StreamReader/StreamWriter for streaming. The using statement ensures proper resource disposal.

  • File.ReadAllLines() — read all lines
  • File.WriteAllLines() — write all lines
  • StreamReader/StreamWriter — streaming I/O
  • Directory — directory operations
csharp
// File I/O in C#
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;

class Program {
    static void Main() {
        // Write to file
        string path = "students.txt";
        string[] lines = {
            "Alice 20 3.85",
            "Bob 22 3.62",
            "Carol 21 3.91"
        };
        File.WriteAllLines(path, lines);

        // Read from file
        string[] content = File.ReadAllLines(path);
        foreach (string line in content) {
            Console.WriteLine(line);
        }

        // Read/Write with StreamReader/StreamWriter
        using (StreamWriter sw = new StreamWriter("output.txt")) {
            sw.WriteLine("Hello, World!");
            sw.WriteLine("Line 2");
        }

        using (StreamReader sr = new StreamReader("output.txt")) {
            string text = sr.ReadToEnd();
            Console.WriteLine(text);
        }

        // File operations
        if (File.Exists("temp.txt")) {
            File.Delete("temp.txt");
        }

        // Directory operations
        Directory.CreateDirectory("testdir");
        Directory.Delete("testdir");

        // FileInfo and DirectoryInfo
        FileInfo fi = new FileInfo("students.txt");
        Console.WriteLine($"File size: {fi.Length} bytes");
        Console.WriteLine($"Created: {fi.CreationTime}");

        // CSV parsing with StringReader
        string csv = "Alice,Bob,Carol,Dave";
        using (StringReader sr = new StringReader(csv)) {
            string line;
            while ((line = sr.ReadLine()) != null) {
                foreach (string token in line.Split(',')) {
                    Console.Write($"{token} ");
                }
                Console.WriteLine();
            }
        }
    }
}
Advanced
18. What are Advanced LINQ features in C#?

LINQ (Language Integrated Query) provides a SQL-like syntax for querying data. Advanced features include GroupJoin, SelectMany, ToLookup, and Aggregate.

  • GroupJoin — left outer join
  • SelectMany — flatten sequences
  • ToLookup — key-based grouping
  • Aggregate — custom reduction/fold
csharp
// LINQ and Functional Programming
using System;
using System.Collections.Generic;
using System.Linq;

class Program {
    static void Main() {
        List<int> nums = new List<int> { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3 };

        // LINQ queries
        var unique = nums.Distinct().OrderBy(x => x).ToList();
        Console.WriteLine($"Unique: {string.Join(" ", unique)}");

        // Aggregation
        Console.WriteLine($"Sum: {nums.Sum()}");
        Console.WriteLine($"Min: {nums.Min()}");
        Console.WriteLine($"Max: {nums.Max()}");
        Console.WriteLine($"Avg: {nums.Average():F2}");

        // Conditional counts
        int evens = nums.Count(x => x % 2 == 0);
        Console.WriteLine($"Evens: {evens}");

        var firstGreater = nums.FirstOrDefault(x => x > 4);
        Console.WriteLine($"First > 4: {firstGreater}");

        // Transform
        var doubled = nums.Select(x => x * 2).ToList();
        Console.WriteLine($"Doubled: {string.Join(" ", doubled)}");

        // Group by
        var grouped = nums.GroupBy(x => x % 2 == 0 ? "Even" : "Odd");
        foreach (var group in grouped) {
            Console.WriteLine($"{group.Key}: {string.Join(", ", group)}");
        }

        // Zip
        List<int> a = new List<int> { 1, 2, 3 };
        List<int> b = new List<int> { 4, 5, 6 };
        var zipped = a.Zip(b, (x, y) => x + y).ToList();
        Console.WriteLine($"Zipped sum: {string.Join(", ", zipped)}");

        // Query syntax
        var query = from x in nums
                    where x > 3
                    orderby x descending
                    select x * 2;
        Console.WriteLine($"Query: {string.Join(", ", query)}");
    }
}
Intermediate
19. How to implement a LinkedList in C#?

A generic LinkedList in C# uses generics for type safety. The class implements PushFront and PushBack methods for O(1) insertions at both ends.

  • Generic node with Data and Next
  • PushFront — O(1) insert at head
  • PushBack — O(n) insert at tail
  • Built-in LinkedList<T> in System.Collections.Generic
csharp
// LinkedList Implementation
using System;
using System.Collections.Generic;

class Node<T> {
    public T Data { get; set; }
    public Node<T> Next { get; set; }

    public Node(T data) {
        Data = data;
        Next = null;
    }
}

class LinkedList<T> {
    private Node<T> head;

    public void PushFront(T val) {
        Node<T> node = new Node<T>(val);
        node.Next = head;
        head = node;
    }

    public void PushBack(T val) {
        Node<T> node = new Node<T>(val);
        if (head == null) {
            head = node;
            return;
        }
        Node<T> curr = head;
        while (curr.Next != null) curr = curr.Next;
        curr.Next = node;
    }

    public void Display() {
        Node<T> curr = head;
        while (curr != null) {
            Console.Write($"{curr.Data} -> ");
            curr = curr.Next;
        }
        Console.WriteLine("null");
    }
}

class Program {
    static void Main() {
        LinkedList<int> list = new LinkedList<int>();
        list.PushBack(10);
        list.PushBack(20);
        list.PushBack(30);
        list.PushFront(5);
        list.Display();
    }
}
Intermediate
20. How do Binary Search and Sorting work in C#?

C# provides built-in BinarySearch() and Sort() methods on List<T> and Array. Find and FindAll offer predicate-based searching.

  • List.BinarySearch() — O(log n) search
  • List.Sort() — O(n log n) in-place sort
  • Array.Sort() — sort arrays
  • Find()/FindAll() — predicate search
csharp
// Binary Search and Sorting
using System;
using System.Collections.Generic;
using System.Linq;

class Program {
    // Manual binary search
    static int BinarySearch(List<int> arr, int target) {
        int left = 0, right = arr.Count - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (arr[mid] == target) return mid;
            else if (arr[mid] < target) left = mid + 1;
            else right = mid - 1;
        }
        return -1;
    }

    static void Main() {
        List<int> arr = new List<int> { 2, 5, 8, 12, 16, 23, 38, 56, 72, 91 };

        // Manual
        Console.WriteLine($"Index of 23: {BinarySearch(arr, 23)}");

        // BinarySearch method
        Console.WriteLine($"Index of 56: {arr.BinarySearch(56)}");

        // Contains
        Console.WriteLine($"Contains 56: {arr.Contains(56)}");

        // Find methods
        int found = arr.Find(x => x > 20);
        Console.WriteLine($"First > 20: {found}");

        // Find all
        var greater = arr.FindAll(x => x > 30);
        Console.WriteLine($" > 30: {string.Join(", ", greater)}");

        // BinarySearch on custom comparer
        arr.Sort();
        int index = arr.BinarySearch(23);
        Console.WriteLine($"Sorted index: {index}");
    }
}
Intermediate
21. How does Recursion work in C#?

Recursion in C# works the same as other languages — a function calling itself. C# supports tail recursion optimization in some cases and provides stackalloc for stack-allocated arrays.

  • Always define a base case
  • Each call creates a new stack frame
  • Recursive async methods are possible
  • Use yield return for lazy recursion
csharp
// Recursion in C#
using System;

class Program {
    static int Factorial(int n) {
        if (n <= 1) return 1;
        return n * Factorial(n - 1);
    }

    static int Fibonacci(int n) {
        if (n <= 1) return n;
        return Fibonacci(n - 1) + Fibonacci(n - 2);
    }

    static void Hanoi(int n, char from, char to, char aux) {
        if (n == 1) {
            Console.WriteLine($"Move disk 1: {from} -> {to}");
            return;
        }
        Hanoi(n - 1, from, aux, to);
        Console.WriteLine($"Move disk {n}: {from} -> {to}");
        Hanoi(n - 1, aux, to, from);
    }

    static int Power(int baseNum, int exp) {
        if (exp == 0) return 1;
        if (exp % 2 == 0) {
            int half = Power(baseNum, exp / 2);
            return half * half;
        }
        return baseNum * Power(baseNum, exp - 1);
    }

    static void Main() {
        Console.WriteLine($"5! = {Factorial(5)}");
        Console.WriteLine($"fib(8) = {Fibonacci(8)}");
        Console.WriteLine($"2^10 = {Power(2, 10)}");
        Console.WriteLine("Tower of Hanoi (3 disks):");
        Hanoi(3, 'A', 'C', 'B');
    }
}
Intermediate
22. How do Sorting Algorithms work in C#?

C# provides built-in sorting via List.Sort() and Array.Sort(). Custom implementations of Bubble Sort, Merge Sort, and Quicksort are common for learning algorithms.

  • Bubble Sort — O(n²), stable
  • Merge Sort — O(n log n), stable, extra space
  • Built-in Sort() — O(n log n), uses introsort
  • Custom comparers for complex objects
csharp
// Sorting Algorithms in C#
using System;
using System.Collections.Generic;
using System.Linq;

class Program {
    static void BubbleSort(List<int> arr) {
        int n = arr.Count;
        for (int i = 0; i < n - 1; i++) {
            bool swapped = false;
            for (int j = 0; j < n - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    swapped = true;
                }
            }
            if (!swapped) break;
        }
    }

    static void MergeSort(List<int> arr, int l, int r) {
        if (l >= r) return;
        int m = l + (r - l) / 2;
        MergeSort(arr, l, m);
        MergeSort(arr, m + 1, r);
        
        List<int> tmp = new List<int>();
        int i = l, j = m + 1;
        while (i <= m && j <= r)
            tmp.Add(arr[i] <= arr[j] ? arr[i++] : arr[j++]);
        while (i <= m) tmp.Add(arr[i++]);
        while (j <= r) tmp.Add(arr[j++]);
        
        for (int k = l; k <= r; k++) arr[k] = tmp[k - l];
    }

    static void Main() {
        List<int> v1 = new List<int> { 64, 34, 25, 12, 22, 11, 90 };
        BubbleSort(v1);
        Console.WriteLine($"Bubble: {string.Join(" ", v1)}");

        List<int> v2 = new List<int> { 38, 27, 43, 3, 9, 82, 10 };
        MergeSort(v2, 0, v2.Count - 1);
        Console.WriteLine($"Merge: {string.Join(" ", v2)}");

        // Built-in sort
        List<int> v3 = new List<int> { 5, 3, 1, 8, 2, 7 };
        v3.Sort();
        Console.WriteLine($"Built-in: {string.Join(" ", v3)}");

        // Sort with comparison
        v3.Sort((a, b) => b.CompareTo(a));
        Console.WriteLine($"Descending: {string.Join(" ", v3)}");
    }
}
Intermediate
23. How does Dynamic Memory work in C#?

C# uses garbage collection for automatic memory management. The new keyword allocates on the heap, and the GC automatically reclaims memory when objects are no longer referenced.

  • new — allocate memory and call constructor
  • Garbage Collector — automatic memory reclamation
  • using — deterministic cleanup for IDisposable
  • GC.Collect() — force collection (rarely needed)
csharp
// Dynamic Memory and Garbage Collection
using System;

class Matrix : IDisposable {
    private int[,] data;
    private int rows, cols;

    public Matrix(int rows, int cols) {
        this.rows = rows;
        this.cols = cols;
        data = new int[rows, cols];
    }

    public void Set(int r, int c, int val) {
        data[r, c] = val;
    }

    public int Get(int r, int c) {
        return data[r, c];
    }

    public void Print() {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                Console.Write($"{data[i, j]} ");
            }
            Console.WriteLine();
        }
    }

    public void Dispose() {
        // Clean up unmanaged resources if any
    }
}

class Program {
    static void Main() {
        // Arrays
        int[] arr = new int[5] { 10, 20, 30, 40, 50 };
        Console.WriteLine(string.Join(" ", arr));

        // Multi-dimensional array
        int[,] matrix = new int[3, 3];
        matrix[0, 0] = 1;
        matrix[1, 1] = 5;
        matrix[2, 2] = 9;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                Console.Write($"{matrix[i, j]} ");
            }
            Console.WriteLine();
        }

        // Jagged array
        int[][] jagged = new int[3][];
        jagged[0] = new int[] { 1, 2 };
        jagged[1] = new int[] { 3, 4, 5 };
        jagged[2] = new int[] { 6 };

        // Garbage Collection
        Console.WriteLine($"Total memory: {GC.GetTotalMemory(false)}");
        GC.Collect();
        Console.WriteLine($"After GC: {GC.GetTotalMemory(false)}");
    }
}
Intermediate
24. How do String Operations work in C#?

C# string is immutable, making operations like concatenation expensive. StringBuilder provides mutable string operations for performance-sensitive scenarios.

  • Substring(), IndexOf(), Contains()
  • Split(), Join(), Replace()
  • StringBuilder — mutable strings
  • String interpolation $"{name}"
csharp
// String Operations in C#
using System;
using System.Text;
using System.Linq;

class Program {
    static void Main() {
        string s = "Hello, World!";

        // Basic operations
        Console.WriteLine($"Length: {s.Length}");
        Console.WriteLine($"Substring: {s.Substring(7, 5)}");
        Console.WriteLine($"Contains: {s.Contains("World")}");
        Console.WriteLine($"Index of: {s.IndexOf("World")}");

        // StringBuilder (mutable string)
        StringBuilder sb = new StringBuilder("Hello");
        sb.Append(", World!");
        sb.Insert(6, " C#");
        sb.Replace("World", "Universe");
        Console.WriteLine(sb.ToString());

        // Case conversion
        string lower = s.ToLower();
        string upper = s.ToUpper();
        Console.WriteLine($"Lower: {lower}");
        Console.WriteLine($"Upper: {upper}");

        // Split and join
        string csv = "Alice,Bob,Carol,Dave";
        string[] tokens = csv.Split(',');
        Console.WriteLine(string.Join(" ", tokens));

        // String interpolation
        string name = "Alice";
        int age = 25;
        Console.WriteLine($"{name} is {age} years old");

        // Trim and padding
        string padded = "  Hello  ";
        Console.WriteLine($"Trimmed: '{padded.Trim()}'");
        Console.WriteLine($"Padded: '{padded.PadLeft(10)}'");

        // Reverse and palindrome
        string pal = "racecar";
        char[] arr = pal.ToCharArray();
        Array.Reverse(arr);
        string reversed = new string(arr);
        Console.WriteLine($"{pal} is palindrome: {pal == reversed}");
    }
}
Advanced
25. What are Interfaces and Abstract Classes in C#?

Interfaces define contracts without implementation. Abstract classes provide partial implementation and cannot be instantiated. C# supports multiple interface inheritance but single class inheritance.

  • Interface — pure contract, multiple inheritance
  • Abstract class — can have implementation, single inheritance
  • Default interface methods (C# 8+)
  • Used for polymorphism and dependency injection
csharp
// Interfaces and Abstract Classes
using System;

// Interface
interface IDrawable {
    void Draw();
    void Resize(double factor);
    double Area { get; }
}

// Abstract class
abstract class Shape : IDrawable {
    public abstract void Draw();
    public abstract void Resize(double factor);
    public abstract double Area { get; }
}

class Circle : Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    public override void Draw() {
        Console.WriteLine($"Drawing Circle r={radius}");
    }

    public override void Resize(double factor) {
        radius *= factor;
    }

    public override double Area {
        get { return Math.PI * radius * radius; }
    }
}

class Square : Shape {
    private double side;

    public Square(double side) {
        this.side = side;
    }

    public override void Draw() {
        Console.WriteLine($"Drawing Square s={side}");
    }

    public override void Resize(double factor) {
        side *= factor;
    }

    public override double Area {
        get { return side * side; }
    }
}

class Program {
    static void Main() {
        List<Shape> shapes = new List<Shape> {
            new Circle(5.0),
            new Square(4.0)
        };

        foreach (var s in shapes) {
            s.Draw();
            Console.WriteLine($"Area: {s.Area:F2}");
            s.Resize(2.0);
            s.Draw();
            Console.WriteLine($"New Area: {s.Area:F2}");
        }
    }
}
Advanced
26. How does Multiple Inheritance work in C#?

C# does not support multiple class inheritance but allows multiple interface inheritance. A class can implement multiple interfaces, combining capabilities from different sources.

  • Implement multiple interfaces with : syntax
  • Explicit interface implementation for conflicts
  • Default interface methods (C# 8+)
  • Used for mixins and capability composition
csharp
// Multiple Inheritance via Interfaces
using System;

interface IVehicle {
    int Speed { get; set; }
    void Move();
}

interface IElectric {
    int Battery { get; set; }
    void Charge();
}

// Multiple interface inheritance
class ElectricCar : IVehicle, IElectric {
    private string model;

    public int Speed { get; set; }
    public int Battery { get; set; }

    public ElectricCar(string model, int speed, int battery) {
        this.model = model;
        Speed = speed;
        Battery = battery;
    }

    public void Display() {
        Console.WriteLine($"Model: {model}");
        Console.WriteLine($"Speed: {Speed} km/h");
        Console.WriteLine($"Battery: {Battery}%");
    }

    public void Move() {
        Console.WriteLine($"{model} glides silently at {Speed} km/h");
    }

    public void Charge() {
        Console.WriteLine($"Charging battery: {Battery}%");
    }
}

class Program {
    static void Main() {
        ElectricCar tesla = new ElectricCar("Tesla Model 3", 250, 85);
        tesla.Display();
        tesla.Move();
        tesla.Charge();
    }
}
Advanced
27. What are Extension Methods in C#?

Extension methods allow adding methods to existing types without modifying them. They are defined as static methods in static classes and use the this keyword.

  • Must be in static class
  • First parameter uses this keyword
  • Cannot access private members
  • Used for LINQ, adding convenience methods
csharp
// Extension Methods and LINQ
using System;
using System.Collections.Generic;
using System.Linq;

public static class StringExtensions {
    public static bool IsPalindrome(this string s) {
        string cleaned = new string(s.Where(char.IsLetterOrDigit).ToArray()).ToLower();
        return cleaned.SequenceEqual(cleaned.Reverse());
    }

    public static string ToTitleCase(this string s) {
        return char.ToUpper(s[0]) + s.Substring(1).ToLower();
    }
}

public static class ListExtensions {
    public static T Second<T>(this List<T> list) {
        if (list.Count < 2) throw new InvalidOperationException("List has less than 2 elements");
        return list[1];
    }

    public static T LastOrDefault<T>(this List<T> list, T defaultValue) {
        return list.Count > 0 ? list[list.Count - 1] : defaultValue;
    }
}

class Program {
    static void Main() {
        // Extension methods on strings
        string text = "racecar";
        Console.WriteLine($"{text} is palindrome: {text.IsPalindrome()}");

        string name = "alice";
        Console.WriteLine($"Title case: {name.ToTitleCase()}");

        // Extension methods on lists
        List<int> numbers = new List<int> { 10, 20, 30, 40 };
        Console.WriteLine($"Second: {numbers.Second()}");
        Console.WriteLine($"LastOrDefault(100): {numbers.LastOrDefault(100)}");

        List<int> empty = new List<int>();
        Console.WriteLine($"Empty LastOrDefault: {empty.LastOrDefault(100)}");

        // Chaining with LINQ
        var result = numbers
            .Where(x => x > 15)
            .Select(x => x * 2)
            .ToList();
        Console.WriteLine($"Chained: {string.Join(", ", result)}");
    }
}
Advanced
28. What are Design Patterns - Singleton and Factory in C#?

The Singleton pattern ensures only one instance exists. The Factory pattern creates objects without exposing creation logic. Both are widely used in C# applications.

  • Singleton: private constructor + static instance
  • Thread-safe singleton with Lazy<T>
  • Factory: returns interface/abstract class
  • Used for dependency injection and object creation
csharp
// Design Patterns - Singleton and Factory
using System;

// Singleton
class Config {
    private static Config instance;
    private string dbUrl = "localhost:5432";

    private Config() { }

    public static Config GetInstance() {
        if (instance == null) instance = new Config();
        return instance;
    }

    public string DbUrl { get { return dbUrl; } set { dbUrl = value; } }
}

// Factory Pattern
interface ILogger {
    void Log(string message);
}

class ConsoleLogger : ILogger {
    public void Log(string message) {
        Console.WriteLine($"[CONSOLE] {message}");
    }
}

class FileLogger : ILogger {
    public void Log(string message) {
        Console.WriteLine($"[FILE] {message}");
    }
}

class LoggerFactory {
    public static ILogger CreateLogger(string type) {
        return type.ToLower() switch {
            "console" => new ConsoleLogger(),
            "file" => new FileLogger(),
            _ => null
        };
    }
}

class Program {
    static void Main() {
        Config cfg = Config.GetInstance();
        Console.WriteLine(cfg.DbUrl);

        ILogger logger = LoggerFactory.CreateLogger("console");
        logger.Log("App started");

        ILogger flog = LoggerFactory.CreateLogger("file");
        flog.Log("Error occurred");
    }
}
Intermediate
29. What are Namespaces in C#?

Namespaces organize code and prevent naming conflicts. The using directive imports namespaces, and using alias creates shorter references.

  • namespace Name — define namespace
  • using — import namespace
  • using Name = Full.Name — alias
  • Nested namespaces with . syntax
csharp
// Namespaces and Using
using System;
using System.Collections.Generic;

namespace MathUtils {
    public const double PI = 3.14159265358979;

    public static class Geometry {
        public static double CircleArea(double r) {
            return PI * r * r;
        }

        public static double RectArea(double w, double h) {
            return w * h;
        }
    }

    namespace Advanced {
        public static class Algebra {
            public static double Power(double baseNum, int exp) {
                double result = 1;
                for (int i = 0; i < exp; i++) result *= baseNum;
                return result;
            }
        }
    }
}

namespace Physics {
    public const double G = 9.81;

    public static class Mechanics {
        public static double KineticEnergy(double m, double v) {
            return 0.5 * m * v * v;
        }

        public static double Weight(double mass) {
            return mass * G;
        }
    }
}

class Program {
    static void Main() {
        using MathUtils.Geometry;
        using MathUtils.Advanced;

        Console.WriteLine($"PI = {MathUtils.PI}");
        Console.WriteLine($"Circle area = {Geometry.CircleArea(5.0)}");
        Console.WriteLine($"2^8 = {Algebra.Power(2, 8)}");
        Console.WriteLine($"Weight(70kg) = {Physics.Mechanics.Weight(70)} N");

        // Using alias
        using Math = MathUtils.Geometry;
        Console.WriteLine($"Rect area = {Math.RectArea(4, 5)}");
    }
}
Intermediate
30. How to solve the Two Sum Problem in C#?

The Two Sum problem uses a Dictionary for O(n) lookup. For each element, check if the complement exists in the dictionary for optimal performance.

  • Dictionary approach: O(n) time, O(n) space
  • Two pointer (sorted): O(n log n) time, O(1) space
  • Tuples for clean pair returns
  • Common coding interview question
csharp
// Two Sum Problem in C#
using System;
using System.Collections.Generic;

class Program {
    // Hash map approach O(n)
    static int[] TwoSum(int[] nums, int target) {
        Dictionary<int, int> map = new Dictionary<int, int>();
        for (int i = 0; i < nums.Length; i++) {
            int complement = target - nums[i];
            if (map.ContainsKey(complement))
                return new int[] { map[complement], i };
            map[nums[i]] = i;
        }
        return new int[] { };
    }

    // Two pointer (sorted input)
    static List<(int, int)> TwoSumPairs(int[] arr, int target) {
        List<(int, int)> result = new List<(int, int)>();
        int l = 0, r = arr.Length - 1;
        while (l < r) {
            int sum = arr[l] + arr[r];
            if (sum == target) {
                result.Add((arr[l], arr[r]));
                l++; r--;
            } else if (sum < target) l++;
            else r--;
        }
        return result;
    }

    static void Main() {
        int[] nums = { 2, 7, 11, 15 };
        int[] res = TwoSum(nums, 9);
        Console.WriteLine($"Indices: [{res[0]}, {res[1]}]");

        int[] sorted = { 1, 2, 3, 4, 6 };
        foreach (var (a, b) in TwoSumPairs(sorted, 6))
            Console.WriteLine($"Pair: {a} + {b}");
    }
}
Advanced
31. How does Kadane's Algorithm work in C#?

Kadane's Algorithm finds the maximum sum contiguous subarray in O(n) time using tuple returns for the sum and indices. Uses int.MinValue for initialization.

  • Track current sum and maximum sum
  • Reset current sum when negative
  • Return tuple with sum, start, end
  • Time O(n), Space O(1)
csharp
// Kadane's Algorithm in C#
using System;
using System.Collections.Generic;

class Program {
    static (int sum, int start, int end) MaxSubarray(int[] arr) {
        int maxSum = int.MinValue, currSum = 0;
        int start = 0, end = 0, tempStart = 0;

        for (int i = 0; i < arr.Length; i++) {
            currSum += arr[i];
            if (currSum > maxSum) {
                maxSum = currSum;
                start = tempStart;
                end = i;
            }
            if (currSum < 0) {
                currSum = 0;
                tempStart = i + 1;
            }
        }
        return (maxSum, start, end);
    }

    static void Main() {
        int[] arr = { -2, 1, -3, 4, -1, 2, 1, -5, 4 };
        var (sum, s, e) = MaxSubarray(arr);

        Console.WriteLine($"Max Sum: {sum}");
        Console.Write("Subarray: ");
        for (int i = s; i <= e; i++) Console.Write($"{arr[i]} ");
        Console.WriteLine();
    }
}
Intermediate
32. How to implement a Binary Tree in C#?

A Binary Tree uses a TreeNode class with left and right references. Level-order insertion uses a Queue to fill the tree level by level.

  • TreeNode with Left and Right
  • Level-order insertion with Queue
  • Inorder traversal: left, root, right
  • Height: 1 + max(left, right)
csharp
// Binary Tree in C#
using System;
using System.Collections.Generic;

class TreeNode {
    public int Val { get; set; }
    public TreeNode Left { get; set; }
    public TreeNode Right { get; set; }

    public TreeNode(int val) {
        Val = val;
        Left = null;
        Right = null;
    }
}

class BinaryTree {
    private TreeNode root;

    public BinaryTree() {
        root = null;
    }

    public void Insert(int val) {
        TreeNode node = new TreeNode(val);
        if (root == null) {
            root = node;
            return;
        }
        Queue<TreeNode> q = new Queue<TreeNode>();
        q.Enqueue(root);
        while (q.Count > 0) {
            TreeNode curr = q.Dequeue();
            if (curr.Left == null) {
                curr.Left = node;
                return;
            } else q.Enqueue(curr.Left);
            if (curr.Right == null) {
                curr.Right = node;
                return;
            } else q.Enqueue(curr.Right);
        }
    }

    public void Inorder() {
        Inorder(root);
        Console.WriteLine();
    }

    private void Inorder(TreeNode node) {
        if (node == null) return;
        Inorder(node.Left);
        Console.Write($"{node.Val} ");
        Inorder(node.Right);
    }

    public int Height() {
        return Height(root);
    }

    private int Height(TreeNode node) {
        if (node == null) return 0;
        return 1 + Math.Max(Height(node.Left), Height(node.Right));
    }
}

class Program {
    static void Main() {
        BinaryTree bt = new BinaryTree();
        foreach (int v in new int[] { 1, 2, 3, 4, 5, 6, 7 }) bt.Insert(v);
        bt.Inorder();
        Console.WriteLine($"Height: {bt.Height()}");
    }
}
Intermediate
33. How to implement a Binary Search Tree in C#?

A BST in C# uses recursive Insert and Search methods. Inorder traversal produces sorted output, confirming the tree structure.

  • Insert: recursively go left/right based on value
  • Search: O(log n) average, O(n) worst
  • Inorder: left, root, right
  • Static methods for clean API
csharp
// Binary Search Tree in C#
using System;

class BST {
    public int Val { get; set; }
    public BST Left { get; set; }
    public BST Right { get; set; }

    public BST(int val) {
        Val = val;
        Left = null;
        Right = null;
    }
}

class Program {
    static BST Insert(BST root, int val) {
        if (root == null) return new BST(val);
        if (val < root.Val) root.Left = Insert(root.Left, val);
        else if (val > root.Val) root.Right = Insert(root.Right, val);
        return root;
    }

    static bool Search(BST root, int val) {
        if (root == null) return false;
        if (root.Val == val) return true;
        return val < root.Val ? Search(root.Left, val)
                              : Search(root.Right, val);
    }

    static void Inorder(BST root) {
        if (root == null) return;
        Inorder(root.Left);
        Console.Write($"{root.Val} ");
        Inorder(root.Right);
    }

    static void Main() {
        BST root = null;
        foreach (int v in new int[] { 50, 30, 70, 20, 40, 60, 80 })
            root = Insert(root, v);

        Inorder(root);
        Console.WriteLine();
        Console.WriteLine($"Search 40: {(Search(root, 40) ? "Found" : "Not found")}");
        Console.WriteLine($"Search 99: {(Search(root, 99) ? "Found" : "Not found")}");
    }
}
Intermediate
34. How to implement BFS and DFS on a Graph in C#?

A Graph class uses List<int>[] for adjacency lists. BFS uses a Queue, DFS uses recursion with a helper method.

  • Adjacency list: List<int>[]
  • BFS: queue + visited array
  • DFS: recursion + visited array
  • Time Complexity O(V+E)
csharp
// Graph BFS and DFS in C#
using System;
using System.Collections.Generic;

class Graph {
    private int V;
    private List<int>[] adj;

    public Graph(int v) {
        V = v;
        adj = new List<int>[v];
        for (int i = 0; i < v; i++) adj[i] = new List<int>();
    }

    public void AddEdge(int u, int v) {
        adj[u].Add(v);
        adj[v].Add(u);
    }

    public void BFS(int start) {
        bool[] visited = new bool[V];
        Queue<int> q = new Queue<int>();
        visited[start] = true;
        q.Enqueue(start);
        Console.Write("BFS: ");
        while (q.Count > 0) {
            int v = q.Dequeue();
            Console.Write($"{v} ");
            foreach (int u in adj[v])
                if (!visited[u]) {
                    visited[u] = true;
                    q.Enqueue(u);
                }
        }
        Console.WriteLine();
    }

    private void DFSHelper(int v, bool[] visited) {
        visited[v] = true;
        Console.Write($"{v} ");
        foreach (int u in adj[v])
            if (!visited[u]) DFSHelper(u, visited);
    }

    public void DFS(int start) {
        bool[] visited = new bool[V];
        Console.Write("DFS: ");
        DFSHelper(start, visited);
        Console.WriteLine();
    }
}

class Program {
    static void Main() {
        Graph g = new Graph(6);
        g.AddEdge(0, 1); g.AddEdge(0, 2);
        g.AddEdge(1, 3); g.AddEdge(2, 4); g.AddEdge(3, 5);
        g.BFS(0);
        g.DFS(0);
    }
}
Advanced
35. How to implement Dijkstra's Algorithm in C#?

Dijkstra's Algorithm uses a SortedSet as a min-heap for O((V+E) log V) performance. Tuples with priority values enable clean heap operations.

  • SortedSet<(int dist, int node)> as min-heap
  • Remove old entries before adding updated distances
  • Time Complexity O((V+E) log V)
  • Only works with non-negative edge weights
csharp
// Dijkstra's Algorithm in C#
using System;
using System.Collections.Generic;
using System.Linq;

class Program {
    static void Dijkstra(List<(int, int)>[] graph, int src) {
        int V = graph.Length;
        int[] dist = Enumerable.Repeat(int.MaxValue, V).ToArray();
        var pq = new SortedSet<(int dist, int node)>();

        dist[src] = 0;
        pq.Add((0, src));

        while (pq.Count > 0) {
            var (d, u) = pq.Min;
            pq.Remove(pq.Min);
            if (d > dist[u]) continue;

            foreach (var (w, v) in graph[u]) {
                if (dist[u] + w < dist[v]) {
                    pq.Remove((dist[v], v));
                    dist[v] = dist[u] + w;
                    pq.Add((dist[v], v));
                }
            }
        }

        Console.WriteLine($"Shortest distances from {src}:");
        for (int i = 0; i < V; i++)
            Console.WriteLine($"  To {i}: {(dist[i] == int.MaxValue ? -1 : dist[i])}");
    }

    static void Main() {
        int V = 5;
        var graph = new List<(int, int)>[V];
        for (int i = 0; i < V; i++) graph[i] = new List<(int, int)>();

        void AddEdge(int u, int v, int w) {
            graph[u].Add((w, v));
            graph[v].Add((w, u));
        }

        AddEdge(0, 1, 10); AddEdge(0, 3, 5);
        AddEdge(1, 2, 1); AddEdge(1, 3, 2);
        AddEdge(2, 4, 4); AddEdge(3, 4, 9);

        Dijkstra(graph, 0);
    }
}
Advanced
36. How to solve Classic DP Problems in C#?

C# 2D arrays (int[,]) are clean for DP tables. 0/1 Knapsack and LCS are foundational DP problems solved with bottom-up tabulation.

  • Knapsack: maximize value within weight capacity
  • LCS: longest common subsequence
  • Time Complexity O(n*W) knapsack, O(m*n) LCS
  • Math.Max() for clean comparisons
csharp
// Dynamic Programming - Classic Problems
using System;
using System.Collections.Generic;

class Program {
    // 0/1 Knapsack
    static int Knapsack(int[] weights, int[] values, int W) {
        int n = weights.Length;
        int[,] dp = new int[n + 1, W + 1];
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= W; j++) {
                dp[i, j] = dp[i - 1, j];
                if (weights[i - 1] <= j)
                    dp[i, j] = Math.Max(dp[i, j],
                        dp[i - 1, j - weights[i - 1]] + values[i - 1]);
            }
        }
        return dp[n, W];
    }

    // Longest Common Subsequence
    static int LCS(string s1, string s2) {
        int m = s1.Length, n = s2.Length;
        int[,] dp = new int[m + 1, n + 1];
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                dp[i, j] = s1[i - 1] == s2[j - 1]
                    ? dp[i - 1, j - 1] + 1
                    : Math.Max(dp[i - 1, j], dp[i, j - 1]);
            }
        }
        return dp[m, n];
    }

    static void Main() {
        int[] weights = { 1, 3, 4, 5 };
        int[] values = { 1, 4, 5, 7 };
        Console.WriteLine($"Knapsack(W=7): {Knapsack(weights, values, 7)}");

        string s1 = "ABCBDAB", s2 = "BDCAB";
        Console.WriteLine($"LCS: {LCS(s1, s2)}");
    }
}
Advanced
37. How to implement a Custom Hash Map in C#?

A custom HashMap uses List<KeyValuePair<K, V>>[] for chaining. The hash function uses GetHashCode() with modulo for bucket indexing.

  • GetHashCode() for key hashing
  • Chaining with List per bucket
  • RemoveAll() for clean deletion
  • Average O(1) operations
csharp
// Hash Map - Custom Implementation
using System;
using System.Collections.Generic;

class HashMap<K, V> {
    private List<KeyValuePair<K, V>>[] table;
    private int capacity;

    public HashMap(int cap = 16) {
        capacity = cap;
        table = new List<KeyValuePair<K, V>>[cap];
        for (int i = 0; i < cap; i++) table[i] = new List<KeyValuePair<K, V>>();
    }

    private int Hash(K key) {
        return Math.Abs(key.GetHashCode()) % capacity;
    }

    public void Put(K key, V value) {
        int idx = Hash(key);
        foreach (var kvp in table[idx]) {
            if (kvp.Key.Equals(key)) {
                table[idx].Remove(kvp);
                break;
            }
        }
        table[idx].Add(new KeyValuePair<K, V>(key, value));
    }

    public V Get(K key) {
        int idx = Hash(key);
        foreach (var kvp in table[idx]) {
            if (kvp.Key.Equals(key)) return kvp.Value;
        }
        throw new KeyNotFoundException($"Key '{key}' not found");
    }

    public bool Contains(K key) {
        int idx = Hash(key);
        foreach (var kvp in table[idx]) {
            if (kvp.Key.Equals(key)) return true;
        }
        return false;
    }

    public void Remove(K key) {
        int idx = Hash(key);
        table[idx].RemoveAll(kvp => kvp.Key.Equals(key));
    }
}

class Program {
    static void Main() {
        HashMap<string, int> map = new HashMap<string, int>();
        map.Put("alice", 90);
        map.Put("bob", 85);
        map.Put("carol", 92);
        Console.WriteLine($"alice: {map.Get("alice")}");
        Console.WriteLine($"Contains bob: {map.Contains("bob")}");
        map.Remove("bob");
        Console.WriteLine($"Contains bob after remove: {map.Contains("bob")}");
    }
}
Advanced
38. How to use Heap and Priority Queue in C#?

C# provides PriorityQueue in .NET 6+. For K Largest Elements, use a min-heap (SortedSet) of size k. Merge K Sorted Arrays uses a custom priority queue.

  • PriorityQueue (.NET 6+) — O(log n) operations
  • SortedSet — min-heap with custom comparer
  • K Largest: min-heap of size k
  • Merge K sorted: tuple with value, array index, element index
csharp
// Heap and Priority Queue in C#
using System;
using System.Collections.Generic;
using System.Linq;

class Program {
    // K largest elements
    static List<int> KLargest(List<int> arr, int k) {
        var minHeap = new SortedSet<(int val, int idx)>();
        for (int i = 0; i < arr.Count; i++) {
            minHeap.Add((arr[i], i));
            if (minHeap.Count > k) minHeap.Remove(minHeap.Min);
        }
        return minHeap.Select(x => x.val).ToList();
    }

    // Merge K sorted arrays
    static List<int> MergeKSorted(List<int>[] arrays) {
        var pq = new SortedSet<(int val, int arrIdx, int elemIdx)>();
        for (int i = 0; i < arrays.Length; i++) {
            if (arrays[i].Count > 0)
                pq.Add((arrays[i][0], i, 0));
        }

        List<int> result = new List<int>();
        while (pq.Count > 0) {
            var (val, i, j) = pq.Min;
            pq.Remove(pq.Min);
            result.Add(val);
            if (j + 1 < arrays[i].Count)
                pq.Add((arrays[i][j + 1], i, j + 1));
        }
        return result;
    }

    static void Main() {
        List<int> arr = new List<int> { 3, 1, 5, 12, 2, 11, 9 };
        var top3 = KLargest(arr, 3);
        Console.WriteLine($"Top 3: {string.Join(" ", top3)}");

        List<int>[] kArr = {
            new List<int> { 1, 4, 7 },
            new List<int> { 2, 5, 8 },
            new List<int> { 3, 6, 9 }
        };
        var merged = MergeKSorted(kArr);
        Console.WriteLine($"Merged: {string.Join(" ", merged)}");
    }
}
Advanced
39. How to implement a Trie in C#?

A Trie in C# uses Dictionary<char, TrieNode> for children. This is more flexible than a fixed 26-element array and handles any character set.

  • Dictionary<char, TrieNode> for children
  • bool IsEnd marks end of word
  • Insert() and Search() — O(L) per operation
  • Used in autocomplete and spell check
csharp
// Trie Data Structure in C#
using System;
using System.Collections.Generic;

class TrieNode {
    public Dictionary<char, TrieNode> Children { get; set; }
    public bool IsEnd { get; set; }

    public TrieNode() {
        Children = new Dictionary<char, TrieNode>();
        IsEnd = false;
    }
}

class Trie {
    private TrieNode root;

    public Trie() {
        root = new TrieNode();
    }

    public void Insert(string word) {
        TrieNode curr = root;
        foreach (char c in word) {
            if (!curr.Children.ContainsKey(c))
                curr.Children[c] = new TrieNode();
            curr = curr.Children[c];
        }
        curr.IsEnd = true;
    }

    public bool Search(string word) {
        TrieNode curr = root;
        foreach (char c in word) {
            if (!curr.Children.ContainsKey(c)) return false;
            curr = curr.Children[c];
        }
        return curr.IsEnd;
    }

    public bool StartsWith(string prefix) {
        TrieNode curr = root;
        foreach (char c in prefix) {
            if (!curr.Children.ContainsKey(c)) return false;
            curr = curr.Children[c];
        }
        return true;
    }
}

class Program {
    static void Main() {
        Trie t = new Trie();
        t.Insert("apple");
        t.Insert("app");
        t.Insert("apply");
        Console.WriteLine($"Search apple: {t.Search("apple")}");
        Console.WriteLine($"Search app: {t.Search("app")}");
        Console.WriteLine($"Search ap: {t.Search("ap")}");
        Console.WriteLine($"StartsWith appl: {t.StartsWith("appl")}");
        Console.WriteLine($"StartsWith xyz: {t.StartsWith("xyz")}");
    }
}
Advanced
40. How to implement a Segment Tree in C#?

A Segment Tree uses an array-based representation. Build, update, and query operations are implemented recursively for range sum queries.

  • Build: O(n) time
  • Query and Update: O(log n) time
  • Tree stored in int[] of size 4*n
  • Supports range sum, min, max queries
csharp
// Segment Tree in C#
using System;
using System.Collections.Generic;

class SegmentTree {
    private int[] tree;
    private int n;

    public SegmentTree(int[] arr) {
        n = arr.Length;
        tree = new int[4 * n];
        Build(arr, 1, 0, n - 1);
    }

    private void Build(int[] arr, int node, int l, int r) {
        if (l == r) {
            tree[node] = arr[l];
            return;
        }
        int mid = (l + r) / 2;
        Build(arr, node * 2, l, mid);
        Build(arr, node * 2 + 1, mid + 1, r);
        tree[node] = tree[node * 2] + tree[node * 2 + 1];
    }

    public void Update(int idx, int val) {
        Update(1, 0, n - 1, idx, val);
    }

    private void Update(int node, int l, int r, int idx, int val) {
        if (l == r) {
            tree[node] = val;
            return;
        }
        int mid = (l + r) / 2;
        if (idx <= mid) Update(node * 2, l, mid, idx, val);
        else Update(node * 2 + 1, mid + 1, r, idx, val);
        tree[node] = tree[node * 2] + tree[node * 2 + 1];
    }

    public int Query(int ql, int qr) {
        return Query(1, 0, n - 1, ql, qr);
    }

    private int Query(int node, int l, int r, int ql, int qr) {
        if (qr < l || r < ql) return 0;
        if (ql <= l && r <= qr) return tree[node];
        int mid = (l + r) / 2;
        return Query(node * 2, l, mid, ql, qr) +
               Query(node * 2 + 1, mid + 1, r, ql, qr);
    }
}

class Program {
    static void Main() {
        int[] arr = { 1, 3, 5, 7, 9, 11 };
        SegmentTree st = new SegmentTree(arr);
        Console.WriteLine($"Sum [1,3]: {st.Query(1, 3)}");
        st.Update(1, 10);
        Console.WriteLine($"Sum [1,3] after update: {st.Query(1, 3)}");
    }
}
Advanced
41. How to implement Union-Find in C#?

A Union-Find (Disjoint Set) uses path compression and union by rank. The Find() method recursively finds the root, and Unite() merges sets.

  • Path compression: parent[x] = Find(parent[x])
  • Union by rank: attach smaller rank under larger
  • Connected() checks if two elements are in the same set
  • Used in Kruskal's MST and connectivity problems
csharp
// Union-Find in C#
using System;

class UnionFind {
    private int[] parent;
    private int[] rank;

    public UnionFind(int n) {
        parent = new int[n];
        rank = new int[n];
        for (int i = 0; i < n; i++) parent[i] = i;
    }

    public int Find(int x) {
        if (parent[x] != x) parent[x] = Find(parent[x]);
        return parent[x];
    }

    public bool Unite(int x, int y) {
        int px = Find(x), py = Find(y);
        if (px == py) return false;
        if (rank[px] < rank[py]) (px, py) = (py, px);
        parent[py] = px;
        if (rank[px] == rank[py]) rank[px]++;
        return true;
    }

    public bool Connected(int x, int y) {
        return Find(x) == Find(y);
    }
}

class Program {
    static void Main() {
        UnionFind uf = new UnionFind(6);
        uf.Unite(0, 1); uf.Unite(1, 2); uf.Unite(3, 4);
        Console.WriteLine($"0-2: {uf.Connected(0, 2)}");
        Console.WriteLine($"0-3: {uf.Connected(0, 3)}");
        uf.Unite(2, 3);
        Console.WriteLine($"0-4 after merge: {uf.Connected(0, 4)}");
    }
}
Advanced
42. How to implement Sliding Window Maximum in C#?

The Sliding Window Maximum uses a LinkedList as a monotonic deque. It stores indices in decreasing order of value, achieving O(n) time.

  • LinkedList<int> as deque
  • Remove out-of-window indices from front
  • Remove smaller elements from rear
  • Front always has the current window maximum
csharp
// Sliding Window Maximum in C#
using System;
using System.Collections.Generic;

class Program {
    static int[] MaxSlidingWindow(int[] nums, int k) {
        LinkedList<int> dq = new LinkedList<int>(); // stores indices
        List<int> result = new List<int>();

        for (int i = 0; i < nums.Length; i++) {
            // Remove out-of-window indices
            while (dq.Count > 0 && dq.First.Value < i - k + 1)
                dq.RemoveFirst();

            // Remove smaller elements from rear
            while (dq.Count > 0 && nums[dq.Last.Value] < nums[i])
                dq.RemoveLast();

            dq.AddLast(i);

            if (i >= k - 1) result.Add(nums[dq.First.Value]);
        }
        return result.ToArray();
    }

    static void Main() {
        int[] nums = { 1, 3, -1, -3, 5, 3, 6, 7 };
        int k = 3;
        int[] res = MaxSlidingWindow(nums, k);
        Console.WriteLine($"Sliding window max: {string.Join(" ", res)}");
    }
}
Advanced
43. How to implement KMP String Matching in C#?

The KMP Algorithm uses an LPS (Longest Proper Prefix which is Suffix) array to skip unnecessary comparisons, achieving O(n+m) time complexity.

  • LPS array computed in O(m)
  • Never moves backward in the text
  • Returns all match positions
  • Time O(n+m), Space O(m)
csharp
// KMP String Matching in C#
using System;
using System.Collections.Generic;

class Program {
    static int[] BuildLPS(string pattern) {
        int m = pattern.Length;
        int[] lps = new int[m];
        int len = 0, i = 1;
        while (i < m) {
            if (pattern[i] == pattern[len]) lps[i++] = ++len;
            else if (len > 0) len = lps[len - 1];
            else lps[i++] = 0;
        }
        return lps;
    }

    static List<int> KMPSearch(string text, string pattern) {
        List<int> positions = new List<int>();
        int[] lps = BuildLPS(pattern);
        int n = text.Length, m = pattern.Length;
        int i = 0, j = 0;

        while (i < n) {
            if (text[i] == pattern[j]) { i++; j++; }
            if (j == m) {
                positions.Add(i - j);
                j = lps[j - 1];
            } else if (i < n && text[i] != pattern[j]) {
                if (j > 0) j = lps[j - 1];
                else i++;
            }
        }
        return positions;
    }

    static void Main() {
        string text = "AABAACAADAABAABA";
        string pat = "AABA";
        var pos = KMPSearch(text, pat);
        Console.WriteLine($"Pattern found at: {string.Join(" ", pos)}");
    }
}
Advanced
44. How to solve the N-Queens Problem in C#?

The N-Queens problem uses backtracking with a 2D array board. The IsSafe() method checks row and diagonals before placing a queen.

  • 2D array int[,] for board
  • Check row and both diagonals
  • Backtrack by resetting cell to 0
  • 8-Queens has 92 solutions
csharp
// N-Queens in C#
using System;

class NQueens {
    private int n;
    private int[,] board;
    private int solutions = 0;

    public NQueens(int n) {
        this.n = n;
        board = new int[n, n];
    }

    private bool IsSafe(int row, int col) {
        for (int j = 0; j < col; j++)
            if (board[row, j] == 1) return false;
        for (int i = row, j = col; i >= 0 && j >= 0; i--, j--)
            if (board[i, j] == 1) return false;
        for (int i = row, j = col; i < n && j >= 0; i++, j--)
            if (board[i, j] == 1) return false;
        return true;
    }

    private void Solve(int col) {
        if (col == n) {
            solutions++;
            if (solutions == 1) {
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < n; j++)
                        Console.Write(board[i, j] == 1 ? "Q " : ". ");
                    Console.WriteLine();
                }
            }
            return;
        }
        for (int row = 0; row < n; row++) {
            if (IsSafe(row, col)) {
                board[row, col] = 1;
                Solve(col + 1);
                board[row, col] = 0;
            }
        }
    }

    public void Run() {
        Solve(0);
        Console.WriteLine($"Total solutions: {solutions}");
    }
}

class Program {
    static void Main() {
        NQueens q = new NQueens(8);
        q.Run();
    }
}
Advanced
45. How to implement an LRU Cache in C#?

An LRU Cache in C# uses a LinkedList for O(1) move-to-front and a Dictionary for O(1) key lookup. Combined they achieve O(1) get and put.

  • LinkedList for cache order
  • Dictionary mapping key to node
  • Evict least recently used when full
  • Time O(1) for both operations
csharp
// LRU Cache in C#
using System;
using System.Collections.Generic;

class LRUCache<K, V> {
    private int capacity;
    private LinkedList<(K key, V value)> cache;
    private Dictionary<K, LinkedListNode<(K, V)>> map;

    public LRUCache(int cap) {
        capacity = cap;
        cache = new LinkedList<(K, V)>();
        map = new Dictionary<K, LinkedListNode<(K, V)>>();
    }

    public V Get(K key) {
        if (!map.ContainsKey(key)) return default(V);
        cache.Remove(map[key]);
        cache.AddFirst(map[key]);
        return map[key].Value.value;
    }

    public void Put(K key, V value) {
        if (map.ContainsKey(key)) {
            cache.Remove(map[key]);
            map.Remove(key);
        }
        if (cache.Count == capacity) {
            var last = cache.Last.Value;
            map.Remove(last.key);
            cache.RemoveLast();
        }
        var node = cache.AddFirst((key, value));
        map[key] = node;
    }
}

class Program {
    static void Main() {
        LRUCache<int, int> lru = new LRUCache<int, int>(2);
        lru.Put(1, 10);
        lru.Put(2, 20);
        Console.WriteLine(lru.Get(1));
        lru.Put(3, 30);
        Console.WriteLine(lru.Get(2));
        Console.WriteLine(lru.Get(3));
    }
}
Advanced
46. How to implement Topological Sort in C#?

Kahn's Algorithm uses an in-degree array and a Queue to produce a topological ordering of a Directed Acyclic Graph (DAG).

  • Calculate in-degree for each vertex
  • Start with zero in-degree vertices in queue
  • Decrement in-degree of neighbors when processing
  • If output size equals V, no cycle exists
csharp
// Graph - Topological Sort in C#
using System;
using System.Collections.Generic;
using System.Linq;

class Program {
    static List<int> TopoSort(int V, List<int>[] adj) {
        int[] inDegree = new int[V];
        for (int u = 0; u < V; u++)
            foreach (int v in adj[u]) inDegree[v]++;

        Queue<int> q = new Queue<int>();
        for (int i = 0; i < V; i++)
            if (inDegree[i] == 0) q.Enqueue(i);

        List<int> order = new List<int>();
        while (q.Count > 0) {
            int u = q.Dequeue();
            order.Add(u);
            foreach (int v in adj[u])
                if (--inDegree[v] == 0) q.Enqueue(v);
        }

        return order.Count == V ? order : new List<int>();
    }

    static void Main() {
        int V = 6;
        List<int>[] adj = new List<int>[V];
        for (int i = 0; i < V; i++) adj[i] = new List<int>();

        adj[5].Add(2); adj[5].Add(0);
        adj[4].Add(0); adj[4].Add(1);
        adj[2].Add(3); adj[3].Add(1);

        var order = TopoSort(V, adj);
        Console.WriteLine($"Topological Order: {string.Join(" ", order)}");
    }
}
Advanced
47. What is Bit Manipulation in C#?

Bit manipulation in C# uses the same operators as C. XOR for finding unique elements and Brian Kernighan's algorithm for bit counting are classic techniques.

  • Operators: &, |, ^, ~, <<, >>
  • XOR trick: a ^ a = 0, a ^ 0 = a
  • Brian Kernighan: n &= n - 1
  • Power of 2 check: (n & (n - 1)) == 0
csharp
// Bit Manipulation in C#
using System;

class Program {
    static bool IsBitSet(int n, int p) => (n & (1 << p)) != 0;
    static int SetBit(int n, int p) => n | (1 << p);
    static int ClearBit(int n, int p) => n & ~(1 << p);
    static int ToggleBit(int n, int p) => n ^ (1 << p);
    static int CountBits(int n) {
        int c = 0;
        while (n > 0) { n &= n - 1; c++; }
        return c;
    }
    static bool IsPowerOf2(int n) => n > 0 && (n & (n - 1)) == 0;

    // Find unique (all others appear twice)
    static int FindUnique(int[] arr) {
        int res = 0;
        foreach (int x in arr) res ^= x;
        return res;
    }

    static void Main() {
        int n = 0b10110100;
        Console.WriteLine($"Number: {n}");
        Console.WriteLine($"Bit 2 set? {IsBitSet(n, 2)}");
        Console.WriteLine($"Set bit 0: {SetBit(n, 0)}");
        Console.WriteLine($"Clear bit 4: {ClearBit(n, 4)}");
        Console.WriteLine($"Toggle bit 7: {ToggleBit(n, 7)}");
        Console.WriteLine($"Count bits: {CountBits(n)}");
        Console.WriteLine($"isPow2(16): {IsPowerOf2(16)}");

        int[] arr = { 2, 3, 5, 4, 5, 3, 4 };
        Console.WriteLine($"Unique: {FindUnique(arr)}");
    }
}
Intermediate
48. How to implement Number Theory algorithms in C#?

C# efficiently implements number theory algorithms like GCD (Euclidean), prime sieve, and modular exponentiation using recursion and bitwise operations.

  • GCD: return b == 0 ? a : GCD(b, a % b)
  • Sieve of Eratosthenes: O(n log log n)
  • Modular exponentiation: O(log n)
  • exp >>= 1 for fast division
csharp
// Number Theory in C#
using System;
using System.Collections.Generic;

class Program {
    static int GCD(int a, int b) => b == 0 ? a : GCD(b, a % b);
    static int LCM(int a, int b) => a / GCD(a, b) * b;

    static bool IsPrime(int n) {
        if (n < 2) return false;
        for (int i = 2; i * i <= n; i++)
            if (n % i == 0) return false;
        return true;
    }

    static List<int> Sieve(int limit) {
        bool[] notPrime = new bool[limit + 1];
        if (limit >= 0) notPrime[0] = true;
        if (limit >= 1) notPrime[1] = true;
        for (int i = 2; i * i <= limit; i++)
            if (!notPrime[i])
                for (int j = i * i; j <= limit; j += i)
                    notPrime[j] = true;
        List<int> primes = new List<int>();
        for (int i = 2; i <= limit; i++)
            if (!notPrime[i]) primes.Add(i);
        return primes;
    }

    static long ModPow(long baseNum, long exp, long mod) {
        long result = 1;
        baseNum %= mod;
        while (exp > 0) {
            if ((exp & 1) == 1) result = result * baseNum % mod;
            baseNum = baseNum * baseNum % mod;
            exp >>= 1;
        }
        return result;
    }

    static void Main() {
        Console.WriteLine($"GCD(48,18)={GCD(48, 18)}");
        Console.WriteLine($"LCM(4,6)={LCM(4, 6)}");
        Console.WriteLine($"isPrime(17)={IsPrime(17)}");

        var primes = Sieve(50);
        Console.WriteLine($"Primes: {string.Join(" ", primes)}");

        Console.WriteLine($"2^10 mod 1000 = {ModPow(2, 10, 1000)}");
    }
}
Intermediate
49. How do Tuple and ValueTuple work in C#?

Tuple is a reference type with Item1, Item2 properties. ValueTuple (C# 7) is a value type with named fields and deconstruction support.

  • Tuple — reference type, heap allocated
  • ValueTuple — value type, stack allocated
  • Named tuple: (string name, int age) person
  • Deconstruction: var (name, age) = person
csharp
// Tuple and ValueTuple in C#
using System;
using System.Collections.Generic;

class Program {
    static void Main() {
        // Tuple
        Tuple<string, int, double> t1 = Tuple.Create("Alice", 25, 3.85);
        Console.WriteLine($"{t1.Item1} age={t1.Item2} gpa={t1.Item3}");

        // ValueTuple (C# 7)
        (string name, int age, double gpa) t2 = ("Bob", 22, 3.62);
        Console.WriteLine($"{t2.name} age={t2.age} gpa={t2.gpa}");

        // Tuple deconstruction
        (string n, int a, double g) = t2;
        Console.WriteLine($"Deconstructed: {n}, {a}, {g}");

        // Named tuple in method return
        var result = GetMinMax(new List<int> { 5, 2, 8, 1, 9 });
        Console.WriteLine($"Min={result.min}, Max={result.max}");

        // Tuple in collections
        List<(string, int)> students = new List<(string, int)> {
            ("Alice", 90), ("Bob", 85), ("Carol", 92)
        };
        students.Sort((a, b) => b.Item2.CompareTo(a.Item2));
        foreach (var (name, score) in students)
            Console.WriteLine($"{name}: {score}");
    }

    static (int min, int max) GetMinMax(List<int> nums) {
        int min = int.MaxValue, max = int.MinValue;
        foreach (int x in nums) {
            if (x < min) min = x;
            if (x > max) max = x;
        }
        return (min, max);
    }
}
Advanced
50. How does the Two Pointers Technique work in C#?

The two pointers technique uses two index variables moving towards each other to solve array problems in O(n) time with O(1) space.

  • Container with most water: maximize area between bars
  • 3-Sum: fix one element, two-pointer the rest
  • Skip duplicates for unique triplets
  • Requires sorted input for most applications
csharp
// Two Pointers Technique in C#
using System;
using System.Collections.Generic;

class Program {
    // Container with most water
    static int MaxWater(int[] height) {
        int l = 0, r = height.Length - 1, maxArea = 0;
        while (l < r) {
            maxArea = Math.Max(maxArea,
                Math.Min(height[l], height[r]) * (r - l));
            if (height[l] < height[r]) l++;
            else r--;
        }
        return maxArea;
    }

    // 3-sum
    static List<List<int>> ThreeSum(int[] nums) {
        Array.Sort(nums);
        List<List<int>> res = new List<List<int>>();
        for (int i = 0; i < nums.Length - 2; i++) {
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            int l = i + 1, r = nums.Length - 1;
            while (l < r) {
                int sum = nums[i] + nums[l] + nums[r];
                if (sum == 0) {
                    res.Add(new List<int> { nums[i], nums[l], nums[r] });
                    while (l < r && nums[l] == nums[l + 1]) l++;
                    while (l < r && nums[r] == nums[r - 1]) r--;
                    l++; r--;
                } else if (sum < 0) l++;
                else r--;
            }
        }
        return res;
    }

    static void Main() {
        int[] h = { 1, 8, 6, 2, 5, 4, 8, 3, 7 };
        Console.WriteLine($"Max water: {MaxWater(h)}");

        int[] nums = { -1, 0, 1, 2, -1, -4 };
        foreach (var triplet in ThreeSum(nums))
            Console.WriteLine(string.Join(" ", triplet));
    }
}
Advanced
51. How does Backtracking work in C#?

Backtracking systematically explores all possibilities by building candidates incrementally and abandoning those that fail constraints. Subsets and permutations are classic examples.

  • Subsets: include/exclude each element
  • Permutations: swap + recurse + swap back
  • List<T> with Add() and RemoveAt()
  • 2ⁿ subsets, n! permutations for n elements
csharp
// Backtracking in C#
using System;
using System.Collections.Generic;

class Program {
    // Generate all subsets
    static List<List<int>> Subsets(int[] nums) {
        List<List<int>> res = new List<List<int>>();
        BacktrackSubsets(nums, 0, new List<int>(), res);
        return res;
    }

    static void BacktrackSubsets(int[] nums, int idx,
                                 List<int> curr, List<List<int>> res) {
        res.Add(new List<int>(curr));
        for (int i = idx; i < nums.Length; i++) {
            curr.Add(nums[i]);
            BacktrackSubsets(nums, i + 1, curr, res);
            curr.RemoveAt(curr.Count - 1);
        }
    }

    // Generate permutations
    static List<List<int>> Permute(int[] nums) {
        List<List<int>> res = new List<List<int>>();
        PermuteHelper(nums, 0, res);
        return res;
    }

    static void PermuteHelper(int[] nums, int start, List<List<int>> res) {
        if (start == nums.Length) {
            res.Add(new List<int>(nums));
            return;
        }
        for (int i = start; i < nums.Length; i++) {
            Swap(nums, start, i);
            PermuteHelper(nums, start + 1, res);
            Swap(nums, start, i);
        }
    }

    static void Swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    static void Main() {
        int[] nums = { 1, 2, 3 };

        var subsets = Subsets(nums);
        Console.WriteLine($"Subsets ({subsets.Count}):");
        foreach (var s in subsets)
            Console.WriteLine($"[{string.Join(" ", s)}]");

        var perms = Permute(nums);
        Console.WriteLine($"Permutations ({perms.Count}):");
        foreach (var p in perms)
            Console.WriteLine(string.Join(" ", p));
    }
}
Advanced
52. How do Greedy Algorithms work in C#?

Greedy algorithms make locally optimal choices. Activity Selection and Fractional Knapsack are classic examples that work with greedy strategy.

  • Activity Selection: sort by end time
  • Fractional Knapsack: sort by value/weight ratio
  • Array.Sort() with custom comparer
  • Tuple sorting with OrderBy
csharp
// Greedy Algorithms in C#
using System;
using System.Collections.Generic;

class Program {
    // Activity Selection
    static int ActivitySelection((int start, int end)[] activities) {
        Array.Sort(activities, (a, b) => a.end.CompareTo(b.end));
        int count = 1, lastEnd = activities[0].end;
        for (int i = 1; i < activities.Length; i++) {
            if (activities[i].start >= lastEnd) {
                count++;
                lastEnd = activities[i].end;
            }
        }
        return count;
    }

    // Fractional Knapsack
    static double FractionalKnapsack((int value, int weight)[] items, int W) {
        Array.Sort(items, (a, b) =>
            ((double)b.value / b.weight).CompareTo((double)a.value / a.weight));
        double total = 0;
        foreach (var (val, wt) in items) {
            if (W >= wt) { total += val; W -= wt; }
            else { total += (double)val / wt * W; break; }
        }
        return total;
    }

    static void Main() {
        (int, int)[] acts = {
            (1, 3), (2, 5), (4, 6), (6, 8), (5, 7)
        };
        Console.WriteLine($"Max activities: {ActivitySelection(acts)}");

        (int, int)[] items = {
            (60, 10), (100, 20), (120, 30)
        };
        Console.WriteLine($"Max value (W=50): {FractionalKnapsack(items, 50)}");
    }
}
Advanced
53. What are Events and Delegates in C#?

Delegates are type-safe function pointers. Events provide a publish/subscribe pattern using delegates. They are used extensively in GUI programming and the Observer pattern.

  • delegate — type-safe callback
  • event — encapsulated multicast delegate
  • EventHandler and EventArgs — standard pattern
  • ?.Invoke() — safe event invocation
csharp
// Events and Delegates in C#
using System;

// Delegate definition
public delegate void PriceChangedEventHandler(object sender, PriceChangedEventArgs e);

// Event args
public class PriceChangedEventArgs : EventArgs {
    public decimal OldPrice { get; }
    public decimal NewPrice { get; }

    public PriceChangedEventArgs(decimal oldPrice, decimal newPrice) {
        OldPrice = oldPrice;
        NewPrice = newPrice;
    }
}

// Subject
class Stock {
    private string symbol;
    private decimal price;

    public event PriceChangedEventHandler PriceChanged;

    public Stock(string symbol, decimal price) {
        this.symbol = symbol;
        this.price = price;
    }

    public decimal Price {
        get { return price; }
        set {
            if (price == value) return;
            decimal old = price;
            price = value;
            OnPriceChanged(old, price);
        }
    }

    protected virtual void OnPriceChanged(decimal oldPrice, decimal newPrice) {
        PriceChanged?.Invoke(this, new PriceChangedEventArgs(oldPrice, newPrice));
    }
}

// Observer
class Investor {
    private string name;

    public Investor(string name) {
        this.name = name;
    }

    public void HandlePriceChange(object sender, PriceChangedEventArgs e) {
        Console.WriteLine(name + " notified: Price changed from $" + e.OldPrice + " to $" + e.NewPrice);
    }
}

class Program {
    static void Main() {
        Stock apple = new Stock("AAPL", 150);
        Investor alice = new Investor("Alice");
        Investor bob = new Investor("Bob");

        apple.PriceChanged += alice.HandlePriceChange;
        apple.PriceChanged += bob.HandlePriceChange;

        apple.Price = 155;
        apple.Price = 160;
    }
}
Advanced
54. What is IDisposable and Resource Management in C#?

IDisposable provides deterministic resource cleanup. The using statement ensures Dispose() is called even with exceptions, following the RAII pattern.

  • IDisposable — implement Dispose()
  • using statement — auto-dispose
  • using declaration (C# 8+) — scoped disposal
  • Used for file handles, database connections, mutexes
csharp
// IDisposable and Resource Management
using System;
using System.IO;

class FileHandler : IDisposable {
    private StreamWriter writer;
    private string filename;

    public FileHandler(string name) {
        filename = name;
        writer = new StreamWriter(name);
        Console.WriteLine($"File opened: {name}");
    }

    public void Write(string data) {
        writer.WriteLine(data);
    }

    public void Dispose() {
        if (writer != null) {
            writer.Close();
            writer.Dispose();
            Console.WriteLine($"File closed: {filename}");
        }
    }
}

class Program {
    static void Main() {
        // Using statement - auto dispose
        using (FileHandler fh = new FileHandler("test.txt")) {
            fh.Write("Hello RAII!");
            fh.Write("Line 2");
        }  // Auto-disposed here

        // Using declaration (C# 8+)
        using FileHandler fh2 = new FileHandler("test2.txt");
        fh2.Write("Data");
        // Auto-disposed at end of scope

        // Manual disposal with try-finally
        FileHandler fh3 = null;
        try {
            fh3 = new FileHandler("test3.txt");
            fh3.Write("Data");
        } finally {
            fh3?.Dispose();
        }
    }
}
Advanced
55. How does Async and Parallel Programming work in C#?

C# supports async/await for asynchronous I/O, Parallel.For for CPU-bound work, and PLINQ for parallel data processing. CancellationToken enables graceful cancellation.

  • async/await — non-blocking I/O
  • Parallel.For — parallel loops
  • PLINQ: AsParallel() for parallel LINQ
  • CancellationToken — cancellation support
csharp
// Async and Parallel Programming
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;

class Program {
    static async Task Main() {
        // Parallel.For
        Console.WriteLine("Parallel.For:");
        Parallel.For(0, 10, i => {
            Thread.Sleep(100);
            Console.WriteLine($"Task {i} on thread {Thread.CurrentThread.ManagedThreadId}");
        });

        // Parallel.ForEach
        Console.WriteLine("
Parallel.ForEach:");
        var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        Parallel.ForEach(numbers, n => {
            Console.WriteLine($"Square of {n} = {n * n} on thread {Thread.CurrentThread.ManagedThreadId}");
        });

        // PLINQ
        Console.WriteLine("
PLINQ:");
        var squares = numbers.AsParallel()
            .Select(n => n * n)
            .ToList();
        Console.WriteLine($"Squares: {string.Join(", ", squares)}");

        // Async tasks
        var tasks = new List<Task<int>>();
        for (int i = 0; i < 5; i++) {
            int num = i;
            tasks.Add(Task.Run(() => {
                Thread.Sleep(100);
                return num * num;
            }));
        }

        int[] results = await Task.WhenAll(tasks);
        Console.WriteLine($"Async results: {string.Join(", ", results)}");

        // Cancellation token
        var cts = new CancellationTokenSource();
        cts.CancelAfter(500);

        try {
            await Task.Run(() => {
                for (int i = 0; i < 10; i++) {
                    cts.Token.ThrowIfCancellationRequested();
                    Thread.Sleep(100);
                    Console.WriteLine($"Working... {i}");
                }
            }, cts.Token);
        } catch (OperationCanceledException) {
            Console.WriteLine("Cancelled!");
        }
    }
}
Advanced
56. How to use Regular Expressions in C#?

C#'s Regex class supports powerful pattern matching. Regex.Match() finds matches, Regex.Replace() replaces, and named groups make patterns readable.

  • Regex.IsMatch() — check pattern
  • Regex.Matches() — find all matches
  • Regex.Replace() — replace matches
  • Named groups: (?<name>pattern)
csharp
// Regular Expressions in C#
using System;
using System.Text.RegularExpressions;

class Program {
    static void Main() {
        // Email validation
        Regex emailRx = new Regex(@"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$");
        string[] emails = { "user@example.com", "invalid-email", "hello@world.org" };
        foreach (string e in emails)
            Console.WriteLine($"{e}: {(emailRx.IsMatch(e) ? "Valid" : "Invalid")}");

        // Search and replace
        string text = "The quick brown fox jumps over the lazy dog";
        string replaced = Regex.Replace(text, @"w{4}", "****");
        Console.WriteLine($"Replaced: {replaced}");

        // Find all matches
        string data = "Price: $100, Discount: $20, Total: $80";
        Regex numRx = new Regex(@"$(d+)");
        MatchCollection matches = numRx.Matches(data);
        Console.Write("Numbers found: ");
        foreach (Match m in matches)
            Console.Write($"{m.Groups[1].Value} ");
        Console.WriteLine();

        // Named groups
        Regex dateRx = new Regex(@"(?<year>d{4})-(?<month>d{2})-(?<day>d{2})");
        Match dateMatch = dateRx.Match("2024-01-15");
        if (dateMatch.Success) {
            Console.WriteLine($"Year: {dateMatch.Groups["year"]}");
            Console.WriteLine($"Month: {dateMatch.Groups["month"]}");
            Console.WriteLine($"Day: {dateMatch.Groups["day"]}");
        }

        // Capture groups
        Regex wordRx = new Regex(@"(w+)s+(w+)");
        string sentence = "Hello World";
        Match match = wordRx.Match(sentence);
        if (match.Success) {
            Console.WriteLine($"Word 1: {match.Groups[1]}");
            Console.WriteLine($"Word 2: {match.Groups[2]}");
        }
    }
}
Advanced
57. What are Attributes and Reflection in C#?

Attributes add metadata to code. Reflection allows inspecting and invoking types at runtime, enabling dynamic behavior and frameworks like dependency injection.

  • Attribute — custom metadata
  • Type — runtime type information
  • MethodInfo.Invoke() — dynamic method invocation
  • Used in serialization, ORM, and testing frameworks
csharp
// Attributes and Reflection in C#
using System;
using System.Reflection;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
class AuthorAttribute : Attribute {
    public string Name { get; }
    public string Version { get; set; }

    public AuthorAttribute(string name) {
        Name = name;
        Version = "1.0";
    }
}

[Author("John Doe")]
class Calculator {
    [Author("Jane Smith", Version = "2.0")]
    public int Add(int a, int b) {
        return a + b;
    }

    public int Multiply(int a, int b) {
        return a * b;
    }
}

class Program {
    static void Main() {
        // Get class attributes
        Type calcType = typeof(Calculator);
        AuthorAttribute classAttr = (AuthorAttribute)Attribute
            .GetCustomAttribute(calcType, typeof(AuthorAttribute));
        if (classAttr != null) {
            Console.WriteLine($"Class Author: {classAttr.Name} (v{classAttr.Version})");
        }

        // Get method attributes
        MethodInfo method = calcType.GetMethod("Add");
        AuthorAttribute methodAttr = (AuthorAttribute)Attribute
            .GetCustomAttribute(method, typeof(AuthorAttribute));
        if (methodAttr != null) {
            Console.WriteLine($"Method Author: {methodAttr.Name} (v{methodAttr.Version})");
        }

        // Reflection - invoke methods
        Calculator calc = new Calculator();
        MethodInfo addMethod = calcType.GetMethod("Add");
        int result = (int)addMethod.Invoke(calc, new object[] { 5, 3 });
        Console.WriteLine($"Add(5,3) = {result}");

        // Get all methods
        Console.WriteLine("
All methods:");
        foreach (var m in calcType.GetMethods()) {
            Console.WriteLine($"  {m.Name}");
        }

        // Dynamic invocation
        MethodInfo multMethod = calcType.GetMethod("Multiply");
        int multResult = (int)multMethod.Invoke(calc, new object[] { 4, 5 });
        Console.WriteLine($"Multiply(4,5) = {multResult}");
    }
}
Advanced
58. What are Design Patterns - Observer and Command in C#?

The Observer pattern uses events/delegates for one-to-many notification. The Command pattern encapsulates operations as objects, enabling undo/redo functionality.

  • Observer: events and delegates
  • Command: Execute() and Undo()
  • History for undo support
  • Widely used in GUI and game development
csharp
// Design Patterns - Observer and Command
using System;
using System.Collections.Generic;

// Observer Pattern
interface IObserver {
    void Update(string eventName, int data);
}

class Subject {
    private List<IObserver> observers = new List<IObserver>();
    private int data;

    public void Subscribe(IObserver o) {
        observers.Add(o);
    }

    public void Unsubscribe(IObserver o) {
        observers.Remove(o);
    }

    public int Data {
        get { return data; }
        set {
            data = value;
            Notify();
        }
    }

    private void Notify() {
        foreach (var o in observers)
            o.Update("Data Changed", data);
    }
}

class ConsoleObserver : IObserver {
    private string name;

    public ConsoleObserver(string name) {
        this.name = name;
    }

    public void Update(string eventName, int data) {
        Console.WriteLine($"{name} notified: {eventName} = {data}");
    }
}

// Command Pattern
interface ICommand {
    void Execute();
    void Undo();
}

class Counter {
    private int value = 0;

    public void Increment(int n) { value += n; }
    public void Decrement(int n) { value -= n; }
    public int Value => value;
}

class IncrementCommand : ICommand {
    private Counter counter;
    private int amount;

    public IncrementCommand(Counter c, int a) {
        counter = c;
        amount = a;
    }

    public void Execute() { counter.Increment(amount); }
    public void Undo() { counter.Decrement(amount); }
}

class Program {
    static void Main() {
        // Observer
        Subject subject = new Subject();
        subject.Subscribe(new ConsoleObserver("Observer1"));
        subject.Subscribe(new ConsoleObserver("Observer2"));
        subject.Data = 42;
        subject.Data = 100;

        // Command
        Counter counter = new Counter();
        List<ICommand> history = new List<ICommand>();
        history.Add(new IncrementCommand(counter, 10));
        history.Add(new IncrementCommand(counter, 5));
        foreach (var cmd in history) cmd.Execute();
        Console.WriteLine($"Counter: {counter.Value}");
        history[history.Count - 1].Undo();
        Console.WriteLine($"After undo: {counter.Value}");
    }
}
Advanced
59. How to implement Functional Programming in C#?

C# supports functional programming with lambdas, higher-order functions, and LINQ. Func and Action delegates enable map, filter, and reduce operations.

  • Select() — map over collection
  • Where() — filter predicate
  • Aggregate() — reduce/fold
  • Memoize with Dictionary cache
csharp
// Functional Programming in C#
using System;
using System.Collections.Generic;
using System.Linq;

class Program {
    // Higher-order functions
    static List<T> Map<T>(List<T> list, Func<T, T> fn) {
        return list.Select(fn).ToList();
    }

    static List<T> Filter<T>(List<T> list, Func<T, bool> pred) {
        return list.Where(pred).ToList();
    }

    static R Reduce<T, R>(List<T> list, R init, Func<R, T, R> fn) {
        return list.Aggregate(init, fn);
    }

    // Function composition
    static Func<T, R> Compose<T, U, R>(Func<U, R> f, Func<T, U> g) {
        return x => f(g(x));
    }

    // Memoization
    static Func<T, R> Memoize<T, R>(Func<T, R> fn) {
        var cache = new Dictionary<T, R>();
        return x => {
            if (!cache.ContainsKey(x)) cache[x] = fn(x);
            return cache[x];
        };
    }

    static void Main() {
        List<int> nums = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        var doubled = Map(nums, x => x * 2);
        Console.WriteLine($"Doubled: {string.Join(" ", doubled)}");

        var evens = Filter(nums, x => x % 2 == 0);
        Console.WriteLine($"Evens: {string.Join(" ", evens)}");

        int sum = Reduce(nums, 0, (a, b) => a + b);
        Console.WriteLine($"Sum: {sum}");

        Func<int, int> addOne = x => x + 1;
        Func<int, int> doubleIt = x => x * 2;
        var addThenDouble = Compose(doubleIt, addOne);
        Console.WriteLine($"Compose(double, +1)(5) = {addThenDouble(5)}");

        // Memoized Fibonacci
        Func<int, int> fib = null;
        fib = n => n <= 1 ? n : fib(n - 1) + fib(n - 2);
        var memoFib = Memoize(fib);
        Console.WriteLine($"fib(30) = {memoFib(30)}");
    }
}
Advanced
60. What are Advanced Generics and Constraints in C#?

Generic constraints (where T : class, new()) restrict the types that can be used as generic arguments. This enables safe and efficient generic code.

  • class constraint — reference types
  • struct constraint — value types
  • new() constraint — parameterless constructor
  • notnull constraint (C# 8+) — non-nullable types
csharp
// Advanced Generics and Constraints in C#
using System;
using System.Collections.Generic;

// Generic constraints
class Repository<T> where T : class, new() {
    private List<T> items = new List<T>();

    public void Add(T item) {
        items.Add(item);
    }

    public T Create() {
        return new T();
    }

    public List<T> GetAll() {
        return items;
    }
}

class Entity {
    public int Id { get; set; }
    public string Name { get; set; }
}

interface IRepository<T> where T : class {
    void Add(T item);
    T Get(int id);
}

class GenericRepository<T> : IRepository<T> where T : class, new() {
    private Dictionary<int, T> items = new Dictionary<int, T>();
    private int nextId = 1;

    public void Add(T item) {
        items[nextId++] = item;
    }

    public T Get(int id) {
        return items.ContainsKey(id) ? items[id] : null;
    }
}

class Program {
    static void Main() {
        Repository<Entity> repo = new Repository<Entity>();
        Entity e1 = repo.Create();
        e1.Name = "Alice";
        repo.Add(e1);
        Entity e2 = repo.Create();
        e2.Name = "Bob";
        repo.Add(e2);

        foreach (var e in repo.GetAll()) {
            Console.WriteLine(e.Name);
        }

        GenericRepository<Entity> genericRepo = new GenericRepository<Entity>();
        genericRepo.Add(new Entity { Name = "Carol" });
        Entity found = genericRepo.Get(1);
        Console.WriteLine($"Found: {found?.Name}");
    }
}
Intermediate
61. How to perform Matrix Operations in C#?

Using 2D arrays (int[,]) makes matrix operations clean. Multiplication, transpose, and rotation are fundamental linear algebra operations.

  • Matrix multiplication: O(r*k*c)
  • Transpose: swap rows and columns
  • 90° CW rotation: transpose then reverse each row
  • Tuple swap for clean code
csharp
// Matrix Operations in C#
using System;

class Program {
    static int[,] Multiply(int[,] A, int[,] B) {
        int r = A.GetLength(0), c = B.GetLength(1), k = A.GetLength(1);
        int[,] C = new int[r, c];
        for (int i = 0; i < r; i++)
            for (int j = 0; j < c; j++)
                for (int p = 0; p < k; p++)
                    C[i, j] += A[i, p] * B[p, j];
        return C;
    }

    static int[,] Transpose(int[,] A) {
        int r = A.GetLength(0), c = A.GetLength(1);
        int[,] T = new int[c, r];
        for (int i = 0; i < r; i++)
            for (int j = 0; j < c; j++)
                T[j, i] = A[i, j];
        return T;
    }

    static void Rotate90(int[,] M) {
        int n = M.GetLength(0);
        // Transpose
        for (int i = 0; i < n; i++)
            for (int j = i + 1; j < n; j++)
                (M[i, j], M[j, i]) = (M[j, i], M[i, j]);
        // Reverse each row
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n / 2; j++)
                (M[i, j], M[i, n - 1 - j]) = (M[i, n - 1 - j], M[i, j]);
    }

    static void Print(int[,] M) {
        int r = M.GetLength(0), c = M.GetLength(1);
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++)
                Console.Write($"{M[i, j]} ");
            Console.WriteLine();
        }
    }

    static void Main() {
        int[,] A = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
        int[,] B = { { 9, 8, 7 }, { 6, 5, 4 }, { 3, 2, 1 } };

        Console.WriteLine("A*B:");
        Print(Multiply(A, B));
        Console.WriteLine("T(A):");
        Print(Transpose(A));
        Rotate90(A);
        Console.WriteLine("A rotated 90CW:");
        Print(A);
    }
}
Advanced
62. How to solve Trapping Rain Water in C#?

The two pointer approach solves Trapping Rain Water in O(n) time and O(1) space by tracking left and right max water levels.

  • Move the side with smaller height inward
  • Track max height seen from each side
  • Time O(n), Space O(1)
  • Ternary operator for compact logic
csharp
// Trapping Rain Water in C#
using System;

class Program {
    static int Trap(int[] height) {
        int l = 0, r = height.Length - 1;
        int leftMax = 0, rightMax = 0, water = 0;
        while (l < r) {
            if (height[l] < height[r]) {
                if (height[l] >= leftMax) leftMax = height[l];
                else water += leftMax - height[l];
                l++;
            } else {
                if (height[r] >= rightMax) rightMax = height[r];
                else water += rightMax - height[r];
                r--;
            }
        }
        return water;
    }

    static void Main() {
        int[] h1 = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
        Console.WriteLine($"Water trapped: {Trap(h1)}");

        int[] h2 = { 4, 2, 0, 3, 2, 5 };
        Console.WriteLine($"Water trapped: {Trap(h2)}");
    }
}
Advanced
63. How to find Longest Increasing Subsequence in C#?

The O(n log n) LIS uses List.BinarySearch() to maintain a sorted tails array. The DP approach is O(n²) but easier to understand.

  • DP: dp[i] = LIS ending at index i
  • Binary search: BinarySearch() replaces in tails
  • Tails length = LIS length
  • O(n log n) time, O(n) space
csharp
// Longest Increasing Subsequence in C#
using System;
using System.Collections.Generic;
using System.Linq;

class Program {
    // DP O(n^2)
    static int LIS_DP(int[] arr) {
        int n = arr.Length;
        int[] dp = Enumerable.Repeat(1, n).ToArray();
        for (int i = 1; i < n; i++)
            for (int j = 0; j < i; j++)
                if (arr[j] < arr[i])
                    dp[i] = Math.Max(dp[i], dp[j] + 1);
        return dp.Max();
    }

    // Binary Search O(n log n)
    static int LIS_BS(int[] arr) {
        List<int> tails = new List<int>();
        foreach (int x in arr) {
            int idx = tails.BinarySearch(x);
            if (idx < 0) idx = ~idx;
            if (idx == tails.Count) tails.Add(x);
            else tails[idx] = x;
        }
        return tails.Count;
    }

    static void Main() {
        int[] arr = { 10, 9, 2, 5, 3, 7, 101, 18 };
        Console.WriteLine($"LIS (DP): {LIS_DP(arr)}");
        Console.WriteLine($"LIS (BS): {LIS_BS(arr)}");
    }
}
Advanced
64. How to implement Bellman-Ford in C#?

Bellman-Ford in C# uses structs for edges. It handles negative weight edges and detects negative weight cycles after V-1 relaxations.

  • Relax all edges V-1 times
  • V-th relaxation detects negative cycle
  • Struct for clean edge representation
  • Time O(V*E), works with negative weights
csharp
// Bellman-Ford in C#
using System;
using System.Collections.Generic;

class Program {
    struct Edge {
        public int u, v, w;
        public Edge(int u, int v, int w) {
            this.u = u;
            this.v = v;
            this.w = w;
        }
    }

    static void BellmanFord(List<Edge> edges, int V, int src) {
        int[] dist = new int[V];
        Array.Fill(dist, int.MaxValue);
        dist[src] = 0;

        for (int i = 1; i < V; i++)
            foreach (var e in edges)
                if (dist[e.u] != int.MaxValue && dist[e.u] + e.w < dist[e.v])
                    dist[e.v] = dist[e.u] + e.w;

        // Check negative cycle
        foreach (var e in edges)
            if (dist[e.u] != int.MaxValue && dist[e.u] + e.w < dist[e.v]) {
                Console.WriteLine("Negative cycle detected!");
                return;
            }

        Console.WriteLine($"Distances from {src}:");
        for (int i = 0; i < V; i++)
            Console.WriteLine($"  {i}: {dist[i]}");
    }

    static void Main() {
        int V = 5;
        List<Edge> edges = new List<Edge> {
            new Edge(0, 1, -1), new Edge(0, 2, 4),
            new Edge(1, 2, 3), new Edge(1, 3, 2),
            new Edge(1, 4, 2), new Edge(3, 2, 5),
            new Edge(3, 1, 1), new Edge(4, 3, -3)
        };
        BellmanFord(edges, V, 0);
    }
}
Advanced
65. How to implement Floyd-Warshall in C#?

Floyd-Warshall computes all-pairs shortest paths in O(V³). C# 2D arrays (int[,]) make the implementation clean with Math.Min() for relaxation.

  • Triple nested loop: k, i, j
  • Check overflow before relaxing
  • Time O(V³), Space O(V²)
  • Handles negative weights but not negative cycles
csharp
// Floyd-Warshall in C#
using System;

class Program {
    static void FloydWarshall(int[,] dist) {
        int V = dist.GetLength(0);
        for (int k = 0; k < V; k++)
            for (int i = 0; i < V; i++)
                for (int j = 0; j < V; j++)
                    if (dist[i, k] != int.MaxValue && dist[k, j] != int.MaxValue)
                        dist[i, j] = Math.Min(dist[i, j],
                            dist[i, k] + dist[k, j]);

        Console.WriteLine("All-Pairs Shortest Paths:");
        for (int i = 0; i < V; i++) {
            for (int j = 0; j < V; j++)
                Console.Write(dist[i, j] == int.MaxValue ? "INF " : $"{dist[i, j],3} ");
            Console.WriteLine();
        }
    }

    static void Main() {
        const int INF = int.MaxValue;
        int[,] graph = {
            {0,   3,   INF, 7  },
            {8,   0,   2,   INF},
            {5,   INF, 0,   1  },
            {2,   INF, INF, 0  }
        };
        FloydWarshall(graph);
    }
}
Advanced
66. How to implement Kruskal's MST in C#?

Kruskal's Algorithm with a DSU class and edge sorting using Sort() produces clean, readable C# code for Minimum Spanning Tree.

  • Sort edges by weight with Sort()
  • DSU class with path compression
  • Find() and Unite() methods
  • Time O(E log E) dominated by sorting
csharp
// Kruskal's MST in C#
using System;
using System.Collections.Generic;
using System.Linq;

class Program {
    struct Edge {
        public int u, v, w;
        public Edge(int u, int v, int w) {
            this.u = u; this.v = v; this.w = w;
        }
    }

    class DSU {
        private int[] parent, rank;

        public DSU(int n) {
            parent = new int[n];
            rank = new int[n];
            for (int i = 0; i < n; i++) parent[i] = i;
        }

        public int Find(int x) {
            if (parent[x] != x) parent[x] = Find(parent[x]);
            return parent[x];
        }

        public bool Unite(int x, int y) {
            int px = Find(x), py = Find(y);
            if (px == py) return false;
            if (rank[px] < rank[py]) (px, py) = (py, px);
            parent[py] = px;
            if (rank[px] == rank[py]) rank[px]++;
            return true;
        }
    }

    static void Main() {
        int V = 4;
        List<Edge> edges = new List<Edge> {
            new Edge(0, 1, 10), new Edge(0, 2, 6),
            new Edge(0, 3, 5), new Edge(1, 3, 15),
            new Edge(2, 3, 4)
        };
        edges.Sort((a, b) => a.w.CompareTo(b.w));

        DSU dsu = new DSU(V);
        int cost = 0;
        Console.WriteLine("MST Edges:");
        foreach (var e in edges)
            if (dsu.Unite(e.u, e.v)) {
                Console.WriteLine($"{e.u} -- {e.v} (weight {e.w})");
                cost += e.w;
            }
        Console.WriteLine($"MST Cost: {cost}");
    }
}
Advanced
67. How to implement advanced String Algorithms in C#?

C# strings support expand-around-center for O(n) longest palindrome, frequency map for anagram check, and sorted key grouping for group anagrams.

  • Palindrome: expand from each center
  • Anagram: Dictionary frequency check
  • Group Anagrams: sorted string as Dictionary key
  • All O(n) or O(n * k log k) time
csharp
// String Algorithms in C#
using System;
using System.Collections.Generic;
using System.Linq;

class Program {
    // Longest palindromic substring
    static string LongestPalindrome(string s) {
        int n = s.Length, start = 0, maxLen = 1;
        void Expand(int l, int r) {
            while (l >= 0 && r < n && s[l] == s[r]) { l--; r++; }
            if (r - l - 1 > maxLen) {
                maxLen = r - l - 1;
                start = l + 1;
            }
        }
        for (int i = 0; i < n; i++) {
            Expand(i, i);
            Expand(i, i + 1);
        }
        return s.Substring(start, maxLen);
    }

    // Check anagram
    static bool IsAnagram(string s1, string s2) {
        if (s1.Length != s2.Length) return false;
        var freq = new Dictionary<char, int>();
        foreach (char c in s1) freq[c] = freq.GetValueOrDefault(c, 0) + 1;
        foreach (char c in s2) {
            if (!freq.ContainsKey(c)) return false;
            if (--freq[c] < 0) return false;
        }
        return true;
    }

    // Group anagrams
    static List<List<string>> GroupAnagrams(string[] words) {
        var map = new Dictionary<string, List<string>>();
        foreach (string w in words) {
            char[] arr = w.ToCharArray();
            Array.Sort(arr);
            string key = new string(arr);
            if (!map.ContainsKey(key)) map[key] = new List<string>();
            map[key].Add(w);
        }
        return map.Values.ToList();
    }

    static void Main() {
        Console.WriteLine(LongestPalindrome("babad"));
        Console.WriteLine(IsAnagram("listen", "silent"));

        string[] words = { "eat", "tea", "tan", "ate", "nat", "bat" };
        foreach (var group in GroupAnagrams(words))
            Console.WriteLine(string.Join(" ", group));
    }
}
Advanced
68. How to solve Coin Change and Subset Sum in C#?

C# arrays make DP table initialization and traversal clean. Coin Change (min coins), Count Ways, and Subset Sum are solved with bottom-up DP.

  • Coin Change: Math.Min() for optimization
  • Count Ways: unbounded knapsack variant
  • Subset Sum: 0/1 knapsack with bool table
  • All O(n * amount) time
csharp
// Coin Change and Subset Sum in C#
using System;
using System.Collections.Generic;

class Program {
    // Minimum coins
    static int CoinChange(int[] coins, int amount) {
        int[] dp = new int[amount + 1];
        Array.Fill(dp, int.MaxValue);
        dp[0] = 0;
        for (int i = 1; i <= amount; i++)
            foreach (int c in coins)
                if (c <= i && dp[i - c] != int.MaxValue)
                    dp[i] = Math.Min(dp[i], dp[i - c] + 1);
        return dp[amount] == int.MaxValue ? -1 : dp[amount];
    }

    // Count ways
    static int CountWays(int[] coins, int amount) {
        int[] dp = new int[amount + 1];
        dp[0] = 1;
        foreach (int c in coins)
            for (int i = c; i <= amount; i++)
                dp[i] += dp[i - c];
        return dp[amount];
    }

    // Subset sum
    static bool SubsetSum(int[] arr, int target) {
        int n = arr.Length;
        bool[,] dp = new bool[n + 1, target + 1];
        for (int i = 0; i <= n; i++) dp[i, 0] = true;
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= target; j++) {
                dp[i, j] = dp[i - 1, j];
                if (arr[i - 1] <= j) dp[i, j] = dp[i, j] || dp[i - 1, j - arr[i - 1]];
            }
        return dp[n, target];
    }

    static void Main() {
        int[] coins = { 1, 5, 6, 9 };
        Console.WriteLine($"Min coins for 11: {CoinChange(coins, 11)}");
        Console.WriteLine($"Ways for 10: {CountWays(coins, 10)}");

        int[] arr = { 3, 34, 4, 12, 5, 2 };
        Console.WriteLine($"Subset sum 9: {SubsetSum(arr, 9)}");
        Console.WriteLine($"Subset sum 30: {SubsetSum(arr, 30)}");
    }
}
Advanced
69. What are Monotonic Stack Problems in C#?

A Monotonic Stack maintains elements in increasing or decreasing order, enabling O(n) solutions for Next Greater Element and Largest Rectangle in Histogram.

  • Pop elements violating monotonic property
  • Next Greater: decreasing stack
  • Histogram: pop and calculate area when height decreases
  • Both O(n) time, O(n) space
csharp
// Monotonic Stack Problems
using System;
using System.Collections.Generic;

class Program {
    // Next Greater Element
    static int[] NextGreater(int[] arr) {
        int n = arr.Length;
        int[] res = new int[n];
        Array.Fill(res, -1);
        Stack<int> st = new Stack<int>();
        for (int i = 0; i < n; i++) {
            while (st.Count > 0 && arr[st.Peek()] < arr[i]) {
                res[st.Pop()] = arr[i];
            }
            st.Push(i);
        }
        return res;
    }

    // Largest Rectangle in Histogram
    static int LargestRect(int[] heights) {
        Stack<int> st = new Stack<int>();
        int maxArea = 0;
        List<int> h = new List<int>(heights) { 0 };
        for (int i = 0; i < h.Count; i++) {
            while (st.Count > 0 && h[st.Peek()] > h[i]) {
                int height = h[st.Pop()];
                int width = st.Count == 0 ? i : i - st.Peek() - 1;
                maxArea = Math.Max(maxArea, height * width);
            }
            st.Push(i);
        }
        return maxArea;
    }

    static void Main() {
        int[] arr = { 4, 5, 2, 10, 8 };
        var ng = NextGreater(arr);
        Console.WriteLine($"Next Greater: {string.Join(" ", ng)}");

        int[] h = { 2, 1, 5, 6, 2, 3 };
        Console.WriteLine($"Largest Rect: {LargestRect(h)}");
    }
}
Advanced
70. What are Binary Search Variants in C#?

Beyond basic binary search, C# enables elegant solutions for rotated sorted arrays, peak elements, and first/last positions using Array.IndexOf() and Array.LastIndexOf().

  • Rotated: determine which half is sorted
  • Peak: move toward the rising side
  • Array.IndexOf() — first occurrence
  • Array.LastIndexOf() — last occurrence
csharp
// Binary Search Variants in C#
using System;
using System.Collections.Generic;

class Program {
    // Search in rotated sorted array
    static int SearchRotated(int[] arr, int target) {
        int l = 0, r = arr.Length - 1;
        while (l <= r) {
            int mid = (l + r) / 2;
            if (arr[mid] == target) return mid;
            if (arr[l] <= arr[mid]) {
                if (target >= arr[l] && target < arr[mid]) r = mid - 1;
                else l = mid + 1;
            } else {
                if (target > arr[mid] && target <= arr[r]) l = mid + 1;
                else r = mid - 1;
            }
        }
        return -1;
    }

    // Find peak element
    static int FindPeak(int[] arr) {
        int l = 0, r = arr.Length - 1;
        while (l < r) {
            int mid = (l + r) / 2;
            if (arr[mid] > arr[mid + 1]) r = mid;
            else l = mid + 1;
        }
        return l;
    }

    // First and last position
    static (int first, int last) FirstLast(int[] arr, int target) {
        int first = Array.IndexOf(arr, target);
        if (first == -1) return (-1, -1);
        int last = Array.LastIndexOf(arr, target);
        return (first, last);
    }

    static void Main() {
        int[] rotated = { 4, 5, 6, 7, 0, 1, 2 };
        Console.WriteLine($"Search 0: {SearchRotated(rotated, 0)}");

        int[] arr = { 1, 2, 3, 1 };
        Console.WriteLine($"Peak index: {FindPeak(arr)}");

        int[] v = { 5, 7, 7, 8, 8, 10 };
        var (f, l) = FirstLast(v, 8);
        Console.WriteLine($"First,Last of 8: {f},{l}");
    }
}
Intermediate
71. How to compute Product of Array Except Self in C#?

A two-pass left/right product approach achieves O(n) time and O(1) extra space. Array.Fill() initializes the result array with 1s.

  • Left pass: prefix products into result
  • Right pass: multiply suffix product
  • Time O(n), Space O(1) extra
  • No division needed — handles zeros
csharp
// Product of Array Except Self in C#
using System;
using System.Collections.Generic;

class Program {
    static int[] ProductExceptSelf(int[] nums) {
        int n = nums.Length;
        int[] result = new int[n];
        Array.Fill(result, 1);

        // Left pass
        for (int i = 1; i < n; i++)
            result[i] = result[i - 1] * nums[i - 1];

        // Right pass
        int right = 1;
        for (int i = n - 1; i >= 0; i--) {
            result[i] *= right;
            right *= nums[i];
        }
        return result;
    }

    static void Main() {
        int[] nums = { 1, 2, 3, 4 };
        var res = ProductExceptSelf(nums);
        Console.WriteLine($"Output: {string.Join(" ", res)}");
    }
}
Advanced
72. How to implement Flood Fill and Number of Islands in C#?

Flood Fill changes all connected same-color pixels. Number of Islands counts connected groups of '1's. Both use DFS with 4-directional traversal.

  • Mark visited cells to avoid reprocessing
  • 4-directional: up, down, left, right
  • Time O(R*C), Space O(R*C) recursion stack
  • Jagged arrays (char[][]) for grid
csharp
// Flood Fill and Number of Islands
using System;
using System.Collections.Generic;

class Program {
    // Flood Fill
    static void FloodFill(int[][] img, int r, int c, int oldColor, int newColor) {
        if (r < 0 || r >= img.Length || c < 0 || c >= img[0].Length) return;
        if (img[r][c] != oldColor || img[r][c] == newColor) return;
        img[r][c] = newColor;
        FloodFill(img, r + 1, c, oldColor, newColor);
        FloodFill(img, r - 1, c, oldColor, newColor);
        FloodFill(img, r, c + 1, oldColor, newColor);
        FloodFill(img, r, c - 1, oldColor, newColor);
    }

    // Number of Islands
    static void DFS(char[][] grid, int r, int c) {
        if (r < 0 || r >= grid.Length || c < 0 || c >= grid[0].Length || grid[r][c] == '0') return;
        grid[r][c] = '0';
        DFS(grid, r + 1, c);
        DFS(grid, r - 1, c);
        DFS(grid, r, c + 1);
        DFS(grid, r, c - 1);
    }

    static int NumIslands(char[][] grid) {
        int count = 0;
        for (int r = 0; r < grid.Length; r++)
            for (int c = 0; c < grid[0].Length; c++)
                if (grid[r][c] == '1') {
                    DFS(grid, r, c);
                    count++;
                }
        return count;
    }

    static void Main() {
        char[][] grid = {
            new char[] { '1', '1', '0', '0' },
            new char[] { '1', '1', '0', '0' },
            new char[] { '0', '0', '1', '0' },
            new char[] { '0', '0', '0', '1' }
        };
        Console.WriteLine($"Islands: {NumIslands(grid)}");
    }
}
Advanced
73. How to implement Word Search in a Grid in C#?

Word Search uses DFS with backtracking. Mark a cell as visited by replacing with '#', recurse in all 4 directions, then restore the cell.

  • Mark cell '#' to prevent reuse
  • Restore cell after DFS
  • Return true as soon as word is found
  • Time O(R*C*4^L) where L is word length
csharp
// Word Search in Grid
using System;
using System.Collections.Generic;

class Program {
    static bool DFS(char[][] board, string word, int r, int c, int idx) {
        if (idx == word.Length) return true;
        if (r < 0 || r >= board.Length || c < 0 || c >= board[0].Length ||
            board[r][c] != word[idx]) return false;

        char tmp = board[r][c];
        board[r][c] = '#';
        bool found = DFS(board, word, r + 1, c, idx + 1) ||
                     DFS(board, word, r - 1, c, idx + 1) ||
                     DFS(board, word, r, c + 1, idx + 1) ||
                     DFS(board, word, r, c - 1, idx + 1);
        board[r][c] = tmp;
        return found;
    }

    static bool WordSearch(char[][] board, string word) {
        for (int r = 0; r < board.Length; r++)
            for (int c = 0; c < board[0].Length; c++)
                if (DFS(board, word, r, c, 0)) return true;
        return false;
    }

    static void Main() {
        char[][] board = {
            new char[] { 'A', 'B', 'C', 'E' },
            new char[] { 'S', 'F', 'C', 'S' },
            new char[] { 'A', 'D', 'E', 'E' }
        };
        Console.WriteLine(WordSearch(board, "ABCCED"));
        Console.WriteLine(WordSearch(board, "SEE"));
        Console.WriteLine(WordSearch(board, "ABCB"));
    }
}
Intermediate
74. How to traverse a Matrix in Spiral Order in C#?

Spiral Matrix Traversal uses four shrinking boundary pointers: top, bottom, left, right. Each pass around the boundary adds elements.

  • Traverse: right → down → left → up
  • Shrink boundaries after each direction
  • Check boundaries before left/up traversal
  • Time O(m*n), Space O(1) excluding result
csharp
// Spiral Matrix in C#
using System;
using System.Collections.Generic;

class Program {
    static List<int> SpiralOrder(int[][] matrix) {
        List<int> res = new List<int>();
        int top = 0, bottom = matrix.Length - 1;
        int left = 0, right = matrix[0].Length - 1;

        while (top <= bottom && left <= right) {
            for (int i = left; i <= right; i++) res.Add(matrix[top][i]);
            top++;
            for (int i = top; i <= bottom; i++) res.Add(matrix[i][right]);
            right--;
            if (top <= bottom) {
                for (int i = right; i >= left; i--) res.Add(matrix[bottom][i]);
                bottom--;
            }
            if (left <= right) {
                for (int i = bottom; i >= top; i--) res.Add(matrix[i][left]);
                left++;
            }
        }
        return res;
    }

    static void Main() {
        int[][] mat = {
            new int[] { 1, 2, 3, 4 },
            new int[] { 5, 6, 7, 8 },
            new int[] { 9, 10, 11, 12 },
            new int[] { 13, 14, 15, 16 }
        };
        Console.WriteLine($"Spiral: {string.Join(" ", SpiralOrder(mat))}");
    }
}
Advanced
75. How to implement a Sudoku Solver in C#?

The Sudoku Solver uses backtracking. For each empty cell, try digits '1'–'9', check row/column/box validity, recurse, and backtrack.

  • Validate row, column, and 3×3 box
  • Box index: 3*(r/3)+i/3, 3*(c/3)+i%3
  • Return true immediately when all cells are filled
  • Classic constraint satisfaction + backtracking
csharp
// Sudoku Solver in C#
using System;

class Program {
    static bool IsValid(char[][] board, int r, int c, char num) {
        for (int i = 0; i < 9; i++) {
            if (board[r][i] == num) return false;
            if (board[i][c] == num) return false;
            if (board[3 * (r / 3) + i / 3][3 * (c / 3) + i % 3] == num) return false;
        }
        return true;
    }

    static bool Solve(char[][] board) {
        for (int r = 0; r < 9; r++) {
            for (int c = 0; c < 9; c++) {
                if (board[r][c] == '.') {
                    for (char num = '1'; num <= '9'; num++) {
                        if (IsValid(board, r, c, num)) {
                            board[r][c] = num;
                            if (Solve(board)) return true;
                            board[r][c] = '.';
                        }
                    }
                    return false;
                }
            }
        }
        return true;
    }

    static void Main() {
        char[][] board = {
            new char[] { '5', '3', '.', '.', '7', '.', '.', '.', '.' },
            new char[] { '6', '.', '.', '1', '9', '5', '.', '.', '.' },
            new char[] { '.', '9', '8', '.', '.', '.', '.', '6', '.' },
            new char[] { '8', '.', '.', '.', '6', '.', '.', '.', '3' },
            new char[] { '4', '.', '.', '8', '.', '3', '.', '.', '1' },
            new char[] { '7', '.', '.', '.', '2', '.', '.', '.', '6' },
            new char[] { '.', '6', '.', '.', '.', '.', '2', '8', '.' },
            new char[] { '.', '.', '.', '4', '1', '9', '.', '.', '5' },
            new char[] { '.', '.', '.', '.', '8', '.', '.', '7', '9' }
        };
        Solve(board);
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++)
                Console.Write($"{board[i][j]} ");
            Console.WriteLine();
        }
    }
}
Advanced
76. How to use Priority Queue with Custom Comparator in C#?

A custom IComparer enables priority queues to order complex objects by multiple criteria — priority first, then deadline, enabling sophisticated scheduling.

  • Implement IComparer<T>
  • PriorityQueue<T, T> with custom comparer
  • Multi-level sorting: primary and tiebreaker
  • Used in job scheduling, event simulation
csharp
// Priority Queue Custom Comparator
using System;
using System.Collections.Generic;

class Task {
    public string Name { get; set; }
    public int Priority { get; set; }
    public int Deadline { get; set; }
}

class TaskComparer : IComparer<Task> {
    public int Compare(Task a, Task b) {
        if (a.Priority != b.Priority) return b.Priority.CompareTo(a.Priority);
        return a.Deadline.CompareTo(b.Deadline);
    }
}

class Program {
    static void Main() {
        var taskQueue = new PriorityQueue<Task, Task>(new TaskComparer());
        taskQueue.Enqueue(new Task { Name = "Write Report", Priority = 3, Deadline = 5 });
        taskQueue.Enqueue(new Task { Name = "Fix Bug", Priority = 5, Deadline = 2 });
        taskQueue.Enqueue(new Task { Name = "Code Review", Priority = 4, Deadline = 3 });
        taskQueue.Enqueue(new Task { Name = "Deploy Feature", Priority = 5, Deadline = 1 });
        taskQueue.Enqueue(new Task { Name = "Write Tests", Priority = 3, Deadline = 4 });

        Console.WriteLine("Task execution order:");
        while (taskQueue.Count > 0) {
            var t = taskQueue.Dequeue();
            Console.WriteLine($"  [P={t.Priority},D={t.Deadline}] {t.Name}");
        }
    }
}
Advanced
77. How to implement Prim's MST in C#?

Prim's Algorithm uses a SortedSet as a min-heap. It grows the MST by picking the minimum weight edge connecting visited to unvisited vertices.

  • Start from vertex 0 with cost 0
  • SortedSet as min-heap
  • Time O((V+E) log V) with priority queue
  • Best for dense graphs vs. Kruskal's for sparse
csharp
// Graph - Prim's MST in C#
using System;
using System.Collections.Generic;

class Program {
    static int PrimMST(List<(int, int)>[] graph, int V) {
        int[] key = new int[V];
        bool[] inMST = new bool[V];
        Array.Fill(key, int.MaxValue);

        var pq = new SortedSet<(int weight, int node)>();
        key[0] = 0;
        pq.Add((0, 0));
        int totalCost = 0;

        while (pq.Count > 0) {
            var (wt, u) = pq.Min;
            pq.Remove(pq.Min);
            if (inMST[u]) continue;
            inMST[u] = true;
            totalCost += wt;

            foreach (var (w, v) in graph[u]) {
                if (!inMST[v] && w < key[v]) {
                    pq.Remove((key[v], v));
                    key[v] = w;
                    pq.Add((key[v], v));
                }
            }
        }
        return totalCost;
    }

    static void Main() {
        int V = 5;
        var graph = new List<(int, int)>[V];
        for (int i = 0; i < V; i++) graph[i] = new List<(int, int)>();

        void AddEdge(int u, int v, int w) {
            graph[u].Add((w, v));
            graph[v].Add((w, u));
        }

        AddEdge(0, 1, 2); AddEdge(0, 3, 6);
        AddEdge(1, 2, 3); AddEdge(1, 3, 8);
        AddEdge(1, 4, 5); AddEdge(2, 4, 7);
        AddEdge(3, 4, 9);

        Console.WriteLine($"MST Cost (Prim's): {PrimMST(graph, V)}");
    }
}
Advanced
78. How to implement Custom Iterator in C#?

A custom iterator is created by implementing IEnumerable<T> and using yield return for lazy evaluation. This enables LINQ and range-based loops.

  • Implement IEnumerable<T>
  • Use yield return for lazy iteration
  • Works seamlessly with LINQ and foreach
  • Custom Fibonacci and Range generators
csharp
// Custom Iterator Pattern in C#
using System;
using System.Collections;
using System.Collections.Generic;

// Custom Range iterator
class Range : IEnumerable<int> {
    private int start, end, step;

    public Range(int start, int end, int step = 1) {
        this.start = start;
        this.end = end;
        this.step = step;
    }

    public IEnumerator<int> GetEnumerator() {
        for (int i = start; i < end; i += step)
            yield return i;
    }

    IEnumerator IEnumerable.GetEnumerator() {
        return GetEnumerator();
    }
}

// Custom Fibonacci generator
class Fibonacci : IEnumerable<long> {
    private int count;

    public Fibonacci(int count) {
        this.count = count;
    }

    public IEnumerator<long> GetEnumerator() {
        long a = 0, b = 1;
        for (int i = 0; i < count; i++) {
            yield return a;
            long c = a + b;
            a = b;
            b = c;
        }
    }

    IEnumerator IEnumerable.GetEnumerator() {
        return GetEnumerator();
    }
}

class Program {
    static void Main() {
        // Custom range
        foreach (int x in new Range(1, 11))
            Console.Write($"{x} ");
        Console.WriteLine();

        foreach (int x in new Range(0, 20, 2))
            Console.Write($"{x} ");
        Console.WriteLine();

        // Custom fibonacci
        foreach (long x in new Fibonacci(10))
            Console.Write($"{x} ");
        Console.WriteLine();

        // LINQ with custom iterator
        var evens = new Range(1, 21).Where(x => x % 2 == 0);
        Console.WriteLine($"Evens: {string.Join(" ", evens)}");

        // Yield return examples
        Console.Write("Manual squares: ");
        foreach (int x in Squares(1, 5))
            Console.Write($"{x} ");
        Console.WriteLine();
    }

    static IEnumerable<int> Squares(int start, int end) {
        for (int i = start; i <= end; i++)
            yield return i * i;
    }
}
Advanced
79. How to implement Custom Stack and Queue in C#?

Custom Stack uses a List<T> with Add() and RemoveAt(). Custom Queue uses LinkedList<T> for O(1) Enqueue/Dequeue.

  • Stack: List<T> with Push() and Pop()
  • Queue: LinkedList<T> with AddLast() and RemoveFirst()
  • Throw InvalidOperationException on empty
  • Use Count property for size
csharp
// Stack and Queue Implementations
using System;
using System.Collections.Generic;

// Custom Stack
class MyStack<T> {
    private List<T> items = new List<T>();

    public void Push(T item) {
        items.Add(item);
    }

    public T Pop() {
        if (IsEmpty()) throw new InvalidOperationException("Stack is empty");
        T item = items[items.Count - 1];
        items.RemoveAt(items.Count - 1);
        return item;
    }

    public T Peek() {
        if (IsEmpty()) throw new InvalidOperationException("Stack is empty");
        return items[items.Count - 1];
    }

    public bool IsEmpty() => items.Count == 0;
    public int Count => items.Count;
}

// Custom Queue
class MyQueue<T> {
    private LinkedList<T> items = new LinkedList<T>();

    public void Enqueue(T item) {
        items.AddLast(item);
    }

    public T Dequeue() {
        if (IsEmpty()) throw new InvalidOperationException("Queue is empty");
        T item = items.First.Value;
        items.RemoveFirst();
        return item;
    }

    public T Peek() {
        if (IsEmpty()) throw new InvalidOperationException("Queue is empty");
        return items.First.Value;
    }

    public bool IsEmpty() => items.Count == 0;
    public int Count => items.Count;
}

class Program {
    static void Main() {
        // Custom Stack
        MyStack<int> stack = new MyStack<int>();
        stack.Push(10);
        stack.Push(20);
        stack.Push(30);
        Console.WriteLine($"Stack top: {stack.Peek()}");
        while (!stack.IsEmpty())
            Console.Write($"{stack.Pop()} ");
        Console.WriteLine();

        // Custom Queue
        MyQueue<int> queue = new MyQueue<int>();
        queue.Enqueue(10);
        queue.Enqueue(20);
        queue.Enqueue(30);
        Console.WriteLine($"Queue front: {queue.Peek()}");
        while (!queue.IsEmpty())
            Console.Write($"{queue.Dequeue()} ");
        Console.WriteLine();
    }
}
Intermediate
80. How to implement Counting Sort and Radix Sort in C#?

Counting Sort is O(n+k) for non-negative integers. Radix Sort applies counting sort digit by digit, achieving O(d*(n+k)) for any integer range.

  • Counting Sort: frequency array then reconstruct
  • Radix Sort: stable sort by each digit position
  • Both are non-comparison sorts
  • Array.Fill() for clean initialization
csharp
// Counting Sort and Radix Sort in C#
using System;
using System.Collections.Generic;

class Program {
    static void CountingSort(List<int> arr) {
        if (arr.Count == 0) return;
        int maxVal = arr[0];
        foreach (int x in arr) if (x > maxVal) maxVal = x;

        int[] count = new int[maxVal + 1];
        foreach (int x in arr) count[x]++;

        int idx = 0;
        for (int i = 0; i <= maxVal; i++)
            while (count[i]-- > 0) arr[idx++] = i;
    }

    static void CountSortByDigit(List<int> arr, int exp) {
        int n = arr.Count;
        int[] output = new int[n];
        int[] count = new int[10];

        foreach (int x in arr) count[(x / exp) % 10]++;

        for (int i = 1; i < 10; i++) count[i] += count[i - 1];

        for (int i = n - 1; i >= 0; i--) {
            int digit = (arr[i] / exp) % 10;
            output[count[digit] - 1] = arr[i];
            count[digit]--;
        }

        for (int i = 0; i < n; i++) arr[i] = output[i];
    }

    static void RadixSort(List<int> arr) {
        int maxVal = arr[0];
        foreach (int x in arr) if (x > maxVal) maxVal = x;

        for (int exp = 1; maxVal / exp > 0; exp *= 10)
            CountSortByDigit(arr, exp);
    }

    static void Main() {
        List<int> v1 = new List<int> { 4, 2, 2, 8, 3, 3, 1, 7, 5 };
        CountingSort(v1);
        Console.WriteLine($"Counting: {string.Join(" ", v1)}");

        List<int> v2 = new List<int> { 170, 45, 75, 90, 802, 24, 2, 66 };
        RadixSort(v2);
        Console.WriteLine($"Radix: {string.Join(" ", v2)}");
    }
}
Advanced
81. How to detect Cycles in a Graph in C#?

Cycle detection differs for directed and undirected graphs. Directed graphs use DFS with a recursion stack. Undirected graphs use Union-Find.

  • Directed: visited + recursion stack
  • Undirected: Union-Find — same component = cycle
  • Local function for recursive find
  • Time O(V+E) for both approaches
csharp
// Graph Cycle Detection in C#
using System;
using System.Collections.Generic;

class Program {
    // Directed graph - DFS with recursion stack
    static bool DFS(int v, List<int>[] adj, bool[] visited, bool[] recStack) {
        visited[v] = recStack[v] = true;
        foreach (int u in adj[v]) {
            if (!visited[u] && DFS(u, adj, visited, recStack))
                return true;
            else if (recStack[u]) return true;
        }
        recStack[v] = false;
        return false;
    }

    static bool HasCycleDirected(int V, List<int>[] adj) {
        bool[] visited = new bool[V];
        bool[] recStack = new bool[V];
        for (int i = 0; i < V; i++)
            if (!visited[i] && DFS(i, adj, visited, recStack))
                return true;
        return false;
    }

    // Undirected graph - Union Find
    static bool HasCycleUndirected(int V, List<(int, int)> edges) {
        int[] parent = new int[V];
        for (int i = 0; i < V; i++) parent[i] = i;

        int Find(int x) {
            if (parent[x] != x) parent[x] = Find(parent[x]);
            return parent[x];
        }

        foreach (var (u, v) in edges) {
            int pu = Find(u), pv = Find(v);
            if (pu == pv) return true;
            parent[pu] = pv;
        }
        return false;
    }

    static void Main() {
        int V = 4;
        List<int>[] adj = new List<int>[V];
        for (int i = 0; i < V; i++) adj[i] = new List<int>();
        adj[0].Add(1); adj[1].Add(2);
        adj[2].Add(3); adj[3].Add(1);

        Console.WriteLine($"Directed cycle: {HasCycleDirected(V, adj)}");

        List<(int, int)> edges = new List<(int, int)> { (0, 1), (1, 2), (2, 0) };
        Console.WriteLine($"Undirected cycle: {HasCycleUndirected(3, edges)}");
    }
}
Advanced
82. What are Advanced LINQ features - GroupJoin, SelectMany, etc.?

GroupJoin performs left outer joins. SelectMany flattens nested sequences. ToLookup creates a dictionary-like lookup structure. Aggregate performs custom reductions.

  • GroupJoin — left outer join with grouping
  • SelectMany — flatten nested collections
  • ToLookup — key-based grouping (like Dictionary)
  • Aggregate — custom fold with seed
csharp
// Advanced LINQ - GroupJoin, SelectMany, etc.
using System;
using System.Collections.Generic;
using System.Linq;

class Program {
    class Customer {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    class Order {
        public int CustomerId { get; set; }
        public string Product { get; set; }
        public int Quantity { get; set; }
    }

    static void Main() {
        var customers = new List<Customer> {
            new Customer { Id = 1, Name = "Alice" },
            new Customer { Id = 2, Name = "Bob" },
            new Customer { Id = 3, Name = "Carol" }
        };

        var orders = new List<Order> {
            new Order { CustomerId = 1, Product = "Laptop", Quantity = 1 },
            new Order { CustomerId = 1, Product = "Mouse", Quantity = 2 },
            new Order { CustomerId = 2, Product = "Keyboard", Quantity = 1 },
            new Order { CustomerId = 2, Product = "Monitor", Quantity = 3 },
            new Order { CustomerId = 2, Product = "Mouse", Quantity = 1 }
        };

        // GroupJoin (left outer join)
        var customerOrders = customers.GroupJoin(
            orders,
            c => c.Id,
            o => o.CustomerId,
            (c, o) => new {
                c.Name,
                Orders = o.Select(x => $"{x.Product} (x{x.Quantity})")
            }
        );

        Console.WriteLine("Customer Orders:");
        foreach (var co in customerOrders) {
            Console.WriteLine($"{co.Name}: {string.Join(", ", co.Orders)}");
        }

        // SelectMany (flatten)
        var allOrderItems = orders.SelectMany(o =>
            Enumerable.Repeat(o.Product, o.Quantity)
        ).ToList();
        Console.WriteLine($"All items: {string.Join(", ", allOrderItems)}");

        // ToLookup
        var orderLookup = orders.ToLookup(o => o.CustomerId);
        foreach (var group in orderLookup) {
            Console.WriteLine($"Customer {group.Key} has {group.Count()} orders");
        }

        // Aggregate with seed
        string allProducts = orders
            .Select(o => o.Product)
            .Aggregate("", (acc, p) => acc == "" ? p : acc + ", " + p);
        Console.WriteLine($"All products: {allProducts}");
    }
}
Advanced
83. How to evaluate expressions using a Stack in C#?

Reverse Polish Notation (RPN) evaluation and Infix to Postfix conversion are classic stack problems. C# Stack and int.Parse() make implementations clean.

  • RPN: push operands, pop two for operators
  • Infix to Postfix: shunting-yard algorithm
  • Precedence function for operator ordering
  • Used in calculators, compilers, and interpreters
csharp
// Expression Evaluation using Stack
using System;
using System.Collections.Generic;

class Program {
    // Evaluate Reverse Polish Notation
    static int EvalRPN(string[] tokens) {
        Stack<int> st = new Stack<int>();
        foreach (string t in tokens) {
            if (t == "+" || t == "-" || t == "*" || t == "/") {
                int b = st.Pop();
                int a = st.Pop();
                st.Push(t == "+" ? a + b :
                       t == "-" ? a - b :
                       t == "*" ? a * b :
                       a / b);
            } else {
                st.Push(int.Parse(t));
            }
        }
        return st.Pop();
    }

    // Infix to Postfix
    static string InfixToPostfix(string expr) {
        Stack<char> ops = new Stack<char>();
        List<string> result = new List<string>();

        int Precedence(char c) {
            return c == '+' || c == '-' ? 1 :
                   c == '*' || c == '/' ? 2 : 0;
        }

        foreach (char c in expr) {
            if (char.IsDigit(c)) {
                result.Add(c.ToString());
            } else if (c == '(') {
                ops.Push(c);
            } else if (c == ')') {
                while (ops.Peek() != '(') result.Add(ops.Pop().ToString());
                ops.Pop();
            } else {
                while (ops.Count > 0 && Precedence(ops.Peek()) >= Precedence(c))
                    result.Add(ops.Pop().ToString());
                ops.Push(c);
            }
        }
        while (ops.Count > 0) result.Add(ops.Pop().ToString());

        return string.Join(" ", result);
    }

    static void Main() {
        string[] rpn = { "2", "1", "+", "3", "*" };
        Console.WriteLine($"RPN eval: {EvalRPN(rpn)}");

        Console.WriteLine($"Infix to Postfix: {InfixToPostfix("(2+3)*4")}");
    }
}
Advanced
84. What are Design Patterns - Strategy and Template in C#?

The Strategy pattern selects an algorithm at runtime. The Template Method defines a skeleton algorithm in a base class with abstract steps.

  • Strategy: interface with Sort() method
  • Context class with SetStrategy()
  • Template Method: abstract class with Process()
  • Concrete implementations override abstract steps
csharp
// Design Patterns - Strategy and Template
using System;
using System.Collections.Generic;

// Strategy Pattern
interface ISortStrategy {
    void Sort(List<int> data);
    string Name { get; }
}

class BubbleSortStrategy : ISortStrategy {
    public string Name => "Bubble Sort";

    public void Sort(List<int> data) {
        int n = data.Count;
        for (int i = 0; i < n - 1; i++) {
            bool swapped = false;
            for (int j = 0; j < n - i - 1; j++) {
                if (data[j] > data[j + 1]) {
                    int temp = data[j];
                    data[j] = data[j + 1];
                    data[j + 1] = temp;
                    swapped = true;
                }
            }
            if (!swapped) break;
        }
    }
}

class BuiltInSortStrategy : ISortStrategy {
    public string Name => "Built-in Sort";

    public void Sort(List<int> data) {
        data.Sort();
    }
}

class SortContext {
    private ISortStrategy strategy;

    public SortContext(ISortStrategy strategy) {
        this.strategy = strategy;
    }

    public void SetStrategy(ISortStrategy strategy) {
        this.strategy = strategy;
    }

    public void Sort(List<int> data) {
        Console.WriteLine($"Using: {strategy.Name}");
        strategy.Sort(data);
    }
}

// Template Method Pattern
abstract class DataProcessor {
    public void Process() {
        LoadData();
        ProcessData();
        SaveResult();
    }

    protected abstract void LoadData();
    protected abstract void ProcessData();
    protected abstract void SaveResult();
}

class CSVProcessor : DataProcessor {
    protected override void LoadData() {
        Console.WriteLine("Loading CSV data...");
    }

    protected override void ProcessData() {
        Console.WriteLine("Processing CSV data...");
    }

    protected override void SaveResult() {
        Console.WriteLine("Saving CSV result...");
    }
}

class Program {
    static void Main() {
        List<int> data = new List<int> { 5, 3, 8, 1, 9, 2 };

        SortContext context = new SortContext(new BubbleSortStrategy());
        context.Sort(new List<int>(data));
        Console.WriteLine(string.Join(" ", data));

        context.SetStrategy(new BuiltInSortStrategy());
        context.Sort(new List<int>(data));
        Console.WriteLine(string.Join(" ", data));

        // Template Method
        Console.WriteLine("
Template Method:");
        DataProcessor processor = new CSVProcessor();
        processor.Process();
    }
}
Advanced
85. How to implement Rabin-Karp String Matching in C#?

Rabin-Karp uses polynomial rolling hash to find pattern matches in O(n+m) average time. C# long handles the hash arithmetic with modulo.

  • Compute pattern hash and initial window hash
  • Roll the hash: remove left, add right
  • Verify match with Substring()
  • Average O(n+m), worst O(n*m)
csharp
// String Matching - Rabin-Karp in C#
using System;
using System.Collections.Generic;

class Program {
    static List<int> RabinKarp(string text, string pattern) {
        List<int> positions = new List<int>();
        int n = text.Length, m = pattern.Length;
        const int BASE = 31;
        const int MOD = 1000000009;

        // Compute hash of pattern and first window
        long patHash = 0, winHash = 0, power = 1;

        for (int i = 0; i < m; i++) {
            patHash = (patHash + (pattern[i] - 'a' + 1) * power) % MOD;
            winHash = (winHash + (text[i] - 'a' + 1) * power) % MOD;
            if (i < m - 1) power = power * BASE % MOD;
        }

        for (int i = 0; i <= n - m; i++) {
            if (patHash == winHash) {
                if (text.Substring(i, m) == pattern)
                    positions.Add(i);
            }
            if (i < n - m) {
                winHash = (winHash - (text[i] - 'a' + 1) + MOD) % MOD;
                winHash = winHash * (MOD + 1 - BASE) % MOD;
                winHash = (winHash + (text[i + m] - 'a' + 1) * power) % MOD;
            }
        }
        return positions;
    }

    static void Main() {
        string text = "aabaacaadaabaaba";
        string pattern = "aaba";
        var pos = RabinKarp(text, pattern);
        Console.WriteLine($"Rabin-Karp found at: {string.Join(" ", pos)}");
    }
}
Advanced
86. What is Type Erasure with dynamic in C#?

dynamic enables runtime type checking and late binding. ExpandoObject provides dynamic objects with properties and methods that can be added at runtime.

  • dynamic — runtime type resolution
  • ExpandoObject — dynamic property and method
  • IDictionary<string, object> — dynamic property access
  • Used for dynamic programming and COM interop
csharp
// Type Erasure with dynamic in C#
using System;
using System.Collections.Generic;
using System.Dynamic;

class Program {
    static void Main() {
        // dynamic type
        dynamic value = 42;
        Console.WriteLine($"Int: {value}");
        value = "Hello, World!";
        Console.WriteLine($"String: {value}");
        value = 3.14159;
        Console.WriteLine($"Double: {value}");

        // ExpandoObject - dynamic object
        dynamic person = new ExpandoObject();
        person.Name = "Alice";
        person.Age = 25;
        person.Greet = new Action(() => {
            Console.WriteLine($"Hello, I'm {person.Name}");
        });
        person.Greet();

        // Dictionary to dynamic
        var dict = new Dictionary<string, object> {
            ["Name"] = "Bob",
            ["Age"] = 30
        };
        dynamic dynDict = new ExpandoObject();
        foreach (var kvp in dict) {
            ((IDictionary<string, object>)dynDict)[kvp.Key] = kvp.Value;
        }
        Console.WriteLine($"{dynDict.Name} is {dynDict.Age} years old");

        // Type checking
        Console.WriteLine($"value is int: {value is int}");
        Console.WriteLine($"value is double: {value is double}");

        // Generic with type parameter
        PrintType(42);
        PrintType("hello");
        PrintType(3.14);
    }

    static void PrintType<T>(T val) {
        Console.WriteLine($"Type: {typeof(T).Name}, Value: {val}");
    }
}
Advanced
87. What is CRTP-style Mixins in C#?

C# mixins can be implemented using default interface methods (C# 8+) or extension methods. Default interface methods provide implementation in interfaces.

  • Default interface methods (C# 8+)
  • Extension methods for static mixins
  • Interface inheritance for capability composition
  • Used for Printable, Comparable, Serializable
csharp
// Advanced OOP - Mixins and Interfaces
using System;

// Interface for printable
interface IPrintable {
    void Print();
}

// Interface for comparable
interface IComparable<T> {
    int CompareTo(T other);
}

// Mixin using default interface methods (C# 8+)
interface IPrintableMixin : IPrintable {
    void PrintWithHeader() {
        Console.WriteLine("=== Print Start ===");
        Print();
        Console.WriteLine("=== Print End ===");
    }
}

// Implementation
class Point : IPrintableMixin, IComparable<Point> {
    private double x, y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }

    public void Print() {
        Console.WriteLine($"Point({x}, {y})");
    }

    public int CompareTo(Point other) {
        double d1 = x * x + y * y;
        double d2 = other.x * other.x + other.y * other.y;
        return d1.CompareTo(d2);
    }

    public double Distance => x * x + y * y;
}

class Program {
    static void Main() {
        Point p1 = new Point(3, 4);
        Point p2 = new Point(1, 1);
        Point p3 = new Point(3, 4);

        p1.Print();
        p1.PrintWithHeader();

        Console.WriteLine($"p1 == p3: {p1.CompareTo(p3) == 0}");
        Console.WriteLine($"p1 > p2: {p1.CompareTo(p2) > 0}");
        Console.WriteLine($"p2 < p1: {p2.CompareTo(p1) < 0}");

        // With LINQ
        var points = new[] { p1, p2, p3 };
        var sorted = points.OrderBy(p => p.Distance);
        Console.WriteLine("Sorted by distance:");
        foreach (var p in sorted) p.Print();
    }
}
Advanced
88. How does Producer-Consumer work with BlockingCollection in C#?

BlockingCollection implements a thread-safe producer-consumer pattern. Add() and GetConsumingEnumerable() provide bounded buffer functionality.

  • BlockingCollection<T> — thread-safe collection
  • Add() — producer adds items
  • GetConsumingEnumerable() — consumer iterates
  • CompleteAdding() — signal completion
csharp
// Concurrency - Producer-Consumer with BlockingCollection
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using System.Threading;

class Program {
    static async Task Main() {
        var buffer = new BlockingCollection<int>(3);

        // Producer
        Task producer = Task.Run(() => {
            for (int i = 1; i <= 6; i++) {
                buffer.Add(i);
                Console.WriteLine($"Produced: {i} | Buffer size: {buffer.Count}");
                Thread.Sleep(100);
            }
            buffer.CompleteAdding();
        });

        // Consumer
        Task consumer = Task.Run(() => {
            foreach (int item in buffer.GetConsumingEnumerable()) {
                Console.WriteLine($"Consumed: {item} | Buffer size: {buffer.Count}");
                Thread.Sleep(150);
            }
        });

        await Task.WhenAll(producer, consumer);

        // ConcurrentBag example
        var bag = new ConcurrentBag<int>();
        Parallel.For(0, 10, i => bag.Add(i));
        Console.WriteLine($"ConcurrentBag count: {bag.Count}");

        // ConcurrentDictionary
        var dict = new ConcurrentDictionary<string, int>();
        dict.TryAdd("one", 1);
        dict.TryAdd("two", 2);
        dict.AddOrUpdate("three", 3, (key, old) => old + 1);
        dict.AddOrUpdate("one", 0, (key, old) => old + 10);
        Console.WriteLine($"ConcurrentDictionary: one={dict["one"]}, three={dict["three"]}");
    }
}
Advanced
89. What are C# 9+ Features - Records and Pattern Matching?

Records (C# 9) provide immutable data types with value equality. Pattern matching has been enhanced with property patterns, tuple patterns, and list patterns.

  • record — immutable data type
  • with expression — create modified copy
  • Property patterns — match on object properties
  • Tuple patterns — match on tuple elements
csharp
// C# 9+ Features - Records and Pattern Matching
using System;

// Records (C# 9)
public record Person(string Name, int Age);

// Record with methods
public record Student(string Name, int Age, string Major) : Person(Name, Age) {
    public void Display() => Console.WriteLine($"{Name} ({Age}) studies {Major}");
}

// Positional record with deconstruction
public record Point(double X, double Y) {
    public double Distance => Math.Sqrt(X * X + Y * Y);
}

class Program {
    static void Main() {
        // Record instantiation
        Person p1 = new Person("Alice", 25);
        Person p2 = new Person("Alice", 25);
        Person p3 = p1 with { Age = 26 };  // With expression

        Console.WriteLine($"p1 == p2: {p1 == p2}");
        Console.WriteLine($"p1: {p1}");
        Console.WriteLine($"p3: {p3}");

        // Pattern matching
        object obj = 42;
        if (obj is int i && i > 10) {
            Console.WriteLine($"Integer: {i}");
        }

        // Switch expression with patterns
        string result = obj switch {
            int n when n > 50 => "Large int",
            int n when n > 10 => "Medium int",
            int n => "Small int",
            string s => $"String: {s}",
            _ => "Unknown"
        };
        Console.WriteLine(result);

        // Property pattern
        if (p1 is Person { Age: 25, Name: "Alice" }) {
            Console.WriteLine("Matched Alice, age 25");
        }

        // Tuple pattern
        var (x, y) = (10, 20);
        string tupleResult = (x, y) switch {
            (0, 0) => "Origin",
            (var a, var b) when a == b => "Equal",
            _ => "Other"
        };
        Console.WriteLine($"Tuple result: {tupleResult}");
    }
}
Advanced
90. What are Advanced C# - Span, Memory, and Performance?

Span<T> provides stack-allocated memory slices. Memory<T> can be on the heap. ArrayPool reuses arrays. These features enable high-performance zero-allocation code.

  • Span<T> — stack-only, no allocation
  • Memory<T> — can be on heap
  • ArrayPool<T> — rent and return arrays
  • MemoryMarshal — reinterpret bytes
csharp
// Advanced C# - Span, Memory, and Performance
using System;
using System.Buffers;
using System.Runtime.InteropServices;

class Program {
    static void Main() {
        // Span<T> - stack-only, no allocation
        Span<int> numbers = stackalloc int[5] { 1, 2, 3, 4, 5 };
        Console.WriteLine($"Span: {string.Join(", ", numbers.ToArray())}");

        // Slice
        var slice = numbers.Slice(1, 3);
        Console.WriteLine($"Slice: {string.Join(", ", slice.ToArray())}");

        // Modify slice affects original
        slice[0] = 99;
        Console.WriteLine($"After slice modification: {string.Join(", ", numbers.ToArray())}");

        // Memory<T> - can be on heap
        Memory<int> memory = new int[] { 10, 20, 30, 40, 50 };
        var memorySlice = memory.Slice(1, 3);
        Console.WriteLine($"Memory slice: {string.Join(", ", memorySlice.ToArray())}");

        // ArrayPool - rent and return
        int[] pooled = ArrayPool<int>.Shared.Rent(10);
        try {
            for (int i = 0; i < 10; i++) pooled[i] = i * 2;
            Console.WriteLine($"Pooled: {string.Join(", ", pooled[..10])}");
        } finally {
            ArrayPool<int>.Shared.Return(pooled);
        }

        // Unsafe and MemoryMarshal
        byte[] bytes = { 1, 2, 3, 4 };
        int intValue = MemoryMarshal.Read<int>(bytes);
        Console.WriteLine($"Bytes as int: {intValue}");

        // String creation with Span
        string text = string.Create(10, 42, (span, state) => {
            span.Fill('*');
            span[0] = 'X';
        });
        Console.WriteLine($"Created: {text}");

        // ReadOnlySpan
        ReadOnlySpan<char> readOnly = "Hello, World!".AsSpan();
        Console.WriteLine($"ReadOnlySpan: {readOnly[..5].ToString()}");
    }
}
Advanced
91. How to use Reflection and Dynamic Invocation in C#?

Reflection enables inspecting and invoking types at runtime. Type.GetMethod() and MethodInfo.Invoke() allow dynamic method calls.

  • Type.GetMethod() — get method info
  • MethodInfo.Invoke() — dynamic invocation
  • Access private fields with BindingFlags
  • Delegate.CreateDelegate() — create typed delegate
csharp
// Reflection and Dynamic Invocation
using System;
using System.Reflection;

class Calculator {
    public int Add(int a, int b) => a + b;
    public int Multiply(int a, int b) => a * b;

    private string _secret = "Hidden";

    private string GetSecret() => _secret;

    public void Print(string message) => Console.WriteLine(message);
}

class Program {
    static void Main() {
        Type calcType = typeof(Calculator);

        // Create instance
        object calc = Activator.CreateInstance(calcType);

        // Get and invoke method
        MethodInfo addMethod = calcType.GetMethod("Add");
        int result = (int)addMethod.Invoke(calc, new object[] { 5, 3 });
        Console.WriteLine($"Add(5,3) = {result}");

        // Get all methods
        Console.WriteLine("
All methods:");
        foreach (var m in calcType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) {
            Console.WriteLine($"  {m.Name} ({(m.IsPublic ? "public" : "private")})");
        }

        // Access private field
        FieldInfo secretField = calcType.GetField("_secret", BindingFlags.NonPublic | BindingFlags.Instance);
        string secret = (string)secretField.GetValue(calc);
        Console.WriteLine($"Private field: {secret}");

        // Invoke private method
        MethodInfo getSecretMethod = calcType.GetMethod("GetSecret", BindingFlags.NonPublic | BindingFlags.Instance);
        string secretValue = (string)getSecretMethod.Invoke(calc, null);
        Console.WriteLine($"Private method: {secretValue}");

        // Dynamic invocation with delegate
        Func<int, int, int> addDelegate = (Func<int, int, int>)Delegate.CreateDelegate(
            typeof(Func<int, int, int>), calc, addMethod);
        Console.WriteLine($"Delegate: {addDelegate(10, 20)}");
    }
}
Advanced
92. What are Advanced LINQ - Dynamic Queries and Expression Trees?

Expression Trees represent code as data, enabling dynamic query construction at runtime. Expression.Lambda() builds predicates dynamically.

  • Expression<T> — code as data
  • Expression.Property() — property access
  • Expression.Lambda() — create lambda
  • Used in dynamic sorting, filtering, projection
csharp
// Advanced LINQ - Dynamic Queries and Expression Trees
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

class Program {
    static void Main() {
        var data = new List<Person> {
            new Person { Name = "Alice", Age = 25, City = "NYC" },
            new Person { Name = "Bob", Age = 30, City = "LA" },
            new Person { Name = "Carol", Age = 22, City = "NYC" },
            new Person { Name = "Dave", Age = 35, City = "Chicago" }
        };

        // Dynamic query building with Expression Trees
        Expression<Func<Person, bool>> filter = p => p.Age > 25 && p.City == "NYC";
        var result = data.AsQueryable().Where(filter).ToList();
        Console.WriteLine($"Filter result: {string.Join(", ", result.Select(p => p.Name))}");

        // Dynamic ordering
        string sortField = "Age";
        var param = Expression.Parameter(typeof(Person), "p");
        var property = Expression.Property(param, sortField);
        var lambda = Expression.Lambda<Func<Person, object>>(Expression.Convert(property, typeof(object)), param);

        var sorted = data.AsQueryable().OrderBy(lambda).ToList();
        Console.WriteLine($"Sorted by Age: {string.Join(", ", sorted.Select(p => $"{p.Name}({p.Age})"))}");

        // Dynamic select
        string[] fields = { "Name", "City" };
        var projections = fields.Select(f => {
            var prop = Expression.Property(param, f);
            return Expression.Lambda<Func<Person, object>>(Expression.Convert(prop, typeof(object)), param);
        }).ToArray();

        Console.WriteLine("Projections:");
        foreach (var p in data) {
            var values = projections.Select(proj => proj.Compile()(p));
            Console.WriteLine($"  {string.Join(", ", values)}");
        }

        // Group by dynamic
        var grouped = data.GroupBy(p => p.City);
        foreach (var g in grouped) {
            Console.WriteLine($"City: {g.Key} ({g.Count()})");
        }
    }

    class Person {
        public string Name { get; set; }
        public int Age { get; set; }
        public string City { get; set; }
    }
}
Advanced
93. How to build a Complete Bank Account System in C#?

A Bank Account System demonstrates real-world C# OOP: encapsulated classes, exception handling, transaction history, inter-account transfers, and formatted output.

  • Transaction history as a list of nested Transaction objects
  • Exception safety: throws on invalid amounts or insufficient funds
  • Console.WriteLine() with formatting for clean output
  • Static field for auto-incrementing account numbers
csharp
// Complete Bank Account System in C#
using System;
using System.Collections.Generic;
using System.Linq;

class BankAccount {
    private static int _nextId = 1000;
    private string _accountId;
    private string _owner;
    private decimal _balance;
    private List<Transaction> _transactions = new List<Transaction>();

    public BankAccount(string owner, decimal initialDeposit = 0) {
        _accountId = "ACC" + (++_nextId);
        _owner = owner;
        _balance = 0;
        if (initialDeposit > 0) Deposit(initialDeposit, "Initial deposit");
    }

    public void Deposit(decimal amount, string description = "Deposit") {
        if (amount <= 0) throw new ArgumentException("Deposit amount must be positive");
        _balance += amount;
        _transactions.Add(new Transaction("DEPOSIT", amount, description, _balance));
    }

    public void Withdraw(decimal amount, string description = "Withdrawal") {
        if (amount <= 0) throw new ArgumentException("Withdrawal amount must be positive");
        if (amount > _balance) throw new InvalidOperationException("Insufficient funds");
        _balance -= amount;
        _transactions.Add(new Transaction("WITHDRAWAL", amount, description, _balance));
    }

    public void Transfer(BankAccount target, decimal amount) {
        Withdraw(amount, "Transfer to " + target._accountId);
        target.Deposit(amount, "Transfer from " + _accountId);
    }

    public void PrintStatement() {
        Console.WriteLine(new string('=', 60));
        Console.WriteLine("Account: " + _accountId + " | Owner: " + _owner + " | Balance: $" + _balance.ToString("F2"));
        Console.WriteLine(new string('-', 60));
        foreach (var t in _transactions) t.Print();
        Console.WriteLine(new string('=', 60));
    }

    public decimal Balance => _balance;
    public string AccountId => _accountId;
    public string Owner => _owner;

    class Transaction {
        public string Type { get; }
        public decimal Amount { get; }
        public string Description { get; }
        public decimal BalanceAfter { get; }
        public DateTime Timestamp { get; }

        public Transaction(string type, decimal amount, string description, decimal balanceAfter) {
            Type = type;
            Amount = amount;
            Description = description;
            BalanceAfter = balanceAfter;
            Timestamp = DateTime.Now;
        }

        public void Print() {
            Console.WriteLine(Timestamp.ToString("HH:mm:ss") + " | " + Type.PadRight(10) + " | $" + Amount.ToString("F2").PadLeft(9) + " | $" + BalanceAfter.ToString("F2").PadLeft(9) + " | " + Description);
        }
    }
}

class Bank {
    private string _name;
    private List<BankAccount> _accounts = new List<BankAccount>();

    public Bank(string name) => _name = name;

    public BankAccount CreateAccount(string owner, decimal initial = 0) {
        var acc = new BankAccount(owner, initial);
        _accounts.Add(acc);
        Console.WriteLine("Account created: " + acc.AccountId + " for " + owner);
        return acc;
    }

    public void ListAccounts() {
        Console.WriteLine("\n=== " + _name + " - All Accounts ===");
        foreach (var acc in _accounts)
            Console.WriteLine(acc.AccountId + " | " + acc.Owner.PadRight(15) + " | Balance: $" + acc.Balance.ToString("F2"));
    }

    public decimal TotalAssets => _accounts.Sum(a => a.Balance);
}

class Program {
    static void Main() {
        Bank bank = new Bank("C# National Bank");

        var alice = bank.CreateAccount("Alice Johnson", 5000);
        var bob = bank.CreateAccount("Bob Smith", 3000);
        var carol = bank.CreateAccount("Carol White", 1000);

        alice.Deposit(2000, "Salary");
        alice.Withdraw(500, "Rent");
        alice.Transfer(bob, 1000);

        try {
            carol.Withdraw(5000);
        } catch (InvalidOperationException e) {
            Console.WriteLine("Error: " + e.Message);
        }

        bob.Deposit(200, "Freelance payment");
        carol.Deposit(3000, "Bonus");
        carol.Transfer(alice, 500);

        alice.PrintStatement();
        bob.PrintStatement();
        carol.PrintStatement();

        bank.ListAccounts();
        Console.WriteLine("Total Assets: $" + bank.TotalAssets.ToString("F2"));
    }
}
Advanced
94. How to implement Iterative Deepening DFS (IDDFS) in C#?

IDDFS combines DFS's space efficiency with BFS's completeness. It repeatedly runs depth-limited DFS with increasing depth limits until the target is found.

  • Combines O(bd) space with BFS optimality
  • Backtrack visited array after each DLS call
  • Finds shortest path in unweighted graphs
  • Used in puzzle solving and game tree search
csharp
// Iterative Deepening DFS (IDDFS) in C#
using System;
using System.Collections.Generic;

class Program {
    static bool DLS(List<int>[] adj, int curr, int target,
                    int depth, bool[] visited) {
        if (curr == target) return true;
        if (depth == 0) return false;
        visited[curr] = true;
        foreach (int next in adj[curr]) {
            if (!visited[next])
                if (DLS(adj, next, target, depth - 1, visited))
                    return true;
        }
        visited[curr] = false;
        return false;
    }

    static bool IDDFS(List<int>[] adj, int src, int target, int maxDepth) {
        for (int depth = 0; depth <= maxDepth; depth++) {
            bool[] visited = new bool[adj.Length];
            Console.WriteLine("Searching at depth " + depth + "...");
            if (DLS(adj, src, target, depth, visited))
                return true;
        }
        return false;
    }

    static void Main() {
        int V = 7;
        List<int>[] adj = new List<int>[V];
        for (int i = 0; i < V; i++) adj[i] = new List<int>();
        adj[0] = new List<int> { 1, 2 };
        adj[1] = new List<int> { 3, 4 };
        adj[2] = new List<int> { 5, 6 };

        Console.WriteLine("IDDFS: Search for node 6 from 0");
        bool found = IDDFS(adj, 0, 6, 5);
        Console.WriteLine("Found: " + (found ? "Yes" : "No"));

        Console.WriteLine("\nIDDFS: Search for node 9 from 0 (not exists)");
        found = IDDFS(adj, 0, 9, 3);
        Console.WriteLine("Found: " + (found ? "Yes" : "No"));
    }
}
Advanced
95. How to implement a Sparse Table for RMQ in C#?

A Sparse Table preprocesses an array in O(n log n) to answer Range Minimum Queries in O(1) time. It exploits overlapping ranges of powers of 2.

  • Build: precompute minimums for all power-of-2 lengths
  • Query: use two overlapping ranges that cover [l, r]
  • Query Time O(1) — fastest possible
  • Cannot handle updates (static structure)
csharp
// Sparse Table for Range Minimum Query
using System;
using System.Collections.Generic;

class SparseTable {
    private int[][] table;
    private int[] log2;

    public SparseTable(int[] arr) {
        int n = arr.Length;
        int LOG = (int)Math.Floor(Math.Log2(n)) + 1;
        table = new int[LOG][];
        log2 = new int[n + 1];

        // Precompute log2
        log2[1] = 0;
        for (int i = 2; i <= n; i++)
            log2[i] = log2[i / 2] + 1;

        // Build sparse table
        table[0] = arr;
        for (int j = 1; j < LOG; j++) {
            table[j] = new int[n - (1 << j) + 1];
            for (int i = 0; i + (1 << j) <= n; i++)
                table[j][i] = Math.Min(table[j - 1][i],
                                      table[j - 1][i + (1 << (j - 1))]);
        }
    }

    public int Query(int l, int r) {
        int k = log2[r - l + 1];
        return Math.Min(table[k][l], table[k][r - (1 << k) + 1]);
    }
}

class Program {
    static void Main() {
        int[] arr = { 2, 4, 3, 1, 6, 7, 8, 9, 1, 7 };
        SparseTable st = new SparseTable(arr);

        Console.WriteLine("RMQ(0,4): " + st.Query(0, 4));
        Console.WriteLine("RMQ(2,7): " + st.Query(2, 7));
        Console.WriteLine("RMQ(5,9): " + st.Query(5, 9));
        Console.WriteLine("RMQ(0,2): " + st.Query(0, 2));
    }
}
Advanced
96. How to implement a Fenwick Tree (BIT) in C#?

A Fenwick Tree (Binary Indexed Tree) supports prefix sum queries and point updates in O(log n). The lowbit operation i & -i is key for traversal.

  • Update: add to i, then i += i & -i
  • Query: sum from i, then i -= i & -i
  • Range query: Query(r) - Query(l-1)
  • Simpler and faster than Segment Tree for sum queries
csharp
// Fenwick Tree (Binary Indexed Tree) in C#
using System;

class FenwickTree {
    private int[] tree;
    private int n;

    public FenwickTree(int n) {
        this.n = n;
        tree = new int[n + 1];
    }

    public void Update(int i, int delta) {
        for (; i <= n; i += i & -i)
            tree[i] += delta;
    }

    public int Query(int i) {
        int sum = 0;
        for (; i > 0; i -= i & -i)
            sum += tree[i];
        return sum;
    }

    public int RangeQuery(int l, int r) => Query(r) - Query(l - 1);

    public void Build(int[] arr) {
        for (int i = 0; i < arr.Length; i++)
            Update(i + 1, arr[i]);
    }
}

class Program {
    static void Main() {
        int[] arr = { 1, 3, 5, 7, 9, 11 };
        FenwickTree ft = new FenwickTree(arr.Length);
        ft.Build(arr);

        Console.WriteLine("Prefix sum [1,3]: " + ft.RangeQuery(1, 3));
        Console.WriteLine("Prefix sum [2,5]: " + ft.RangeQuery(2, 5));
        Console.WriteLine("Total sum: " + ft.RangeQuery(1, 6));

        ft.Update(3, 6);
        Console.WriteLine("After update(3,6):");
        Console.WriteLine("Prefix sum [1,3]: " + ft.RangeQuery(1, 3));
        Console.WriteLine("Total sum: " + ft.RangeQuery(1, 6));
    }
}
Intermediate
97. How to implement Shell Sort and Interpolation Search in C#?

Shell Sort generalizes Insertion Sort using decreasing gap sequences. Interpolation Search estimates position proportionally, achieving O(log log n) on uniform distributions.

  • Shell Sort gap starts at n/2, halves each pass
  • In-place, not stable, better than Insertion Sort
  • Interpolation Search: best for uniform sorted arrays
  • Degrades to O(n) worst case
csharp
// Shell Sort and Interpolation Search in C#
using System;
using System.Collections.Generic;

class Program {
    static void ShellSort(List<int> arr) {
        int n = arr.Count;
        for (int gap = n / 2; gap > 0; gap /= 2) {
            for (int i = gap; i < n; i++) {
                int temp = arr[i], j = i;
                while (j >= gap && arr[j - gap] > temp) {
                    arr[j] = arr[j - gap];
                    j -= gap;
                }
                arr[j] = temp;
            }
        }
    }

    static int InterpolationSearch(int[] arr, int target) {
        int low = 0, high = arr.Length - 1;
        while (low <= high &&
               target >= arr[low] &&
               target <= arr[high]) {
            if (low == high) {
                return arr[low] == target ? low : -1;
            }
            int pos = low + (int)((double)(high - low) /
                         (arr[high] - arr[low]) * (target - arr[low]));
            if (arr[pos] == target) return pos;
            if (arr[pos] < target) low = pos + 1;
            else high = pos - 1;
        }
        return -1;
    }

    static void Main() {
        List<int> arr = new List<int> { 64, 34, 25, 12, 22, 11, 90, 1, 55, 47 };
        Console.WriteLine("Before: " + string.Join(" ", arr));

        ShellSort(arr);
        Console.WriteLine("After Shell Sort: " + string.Join(" ", arr));

        int[] sorted = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
        Console.WriteLine("Search 70: index = " + InterpolationSearch(sorted, 70));
        Console.WriteLine("Search 45: index = " + InterpolationSearch(sorted, 45));
        Console.WriteLine("Search 100: index = " + InterpolationSearch(sorted, 100));
    }
}
Advanced
98. What are Advanced C# - Nullable Reference Types and Pattern Matching?

Nullable reference types (C# 8+) help prevent null reference exceptions. Pattern matching with property patterns, tuple patterns, and list patterns (C# 11) enables concise, readable code.

  • #nullable enable — enable nullable checks
  • string? — nullable reference type
  • Property patterns: { Name: "Alice", Age: 25 }
  • List patterns: [1, 2, 3]
csharp
// Advanced C# - Nullable Reference Types and Pattern Matching
using System;

#nullable enable

class Person {
    public string Name { get; set; } = "";
    public int Age { get; set; }
    public string? Email { get; set; }
}

class Program {
    static void Main() {
        // Nullable reference types
        string? maybeNull = null;
        string notNull = "Hello";

        // Null check
        if (maybeNull != null) {
            Console.WriteLine(maybeNull.Length);
        }

        // Null coalescing
        string value = maybeNull ?? "Default";

        // Null conditional
        int? length = maybeNull?.Length;

        // Pattern matching with null
        string result = maybeNull switch {
            null => "Null value",
            string s when s.Length > 10 => "Long string",
            string s => "Length: " + s.Length,
            _ => "Unknown"
        };
        Console.WriteLine(result);

        // Property pattern matching
        Person person = new Person { Name = "Alice", Age = 25, Email = "alice@email.com" };

        string matchResult = person switch {
            { Name: "Alice", Age: 25 } => "Alice, age 25",
            { Email: not null } => "Has email: " + person.Email,
            _ => "Other"
        };
        Console.WriteLine(matchResult);

        // Tuple pattern
        var tuple = (Name: "Bob", Age: 30);
        string tupleResult = tuple switch {
            ("Bob", 30) => "Bob, 30",
            (_, > 18) => "Adult: " + tuple.Name,
            _ => "Minor"
        };
        Console.WriteLine(tupleResult);

        // List pattern (C# 11)
        int[] numbers = { 1, 2, 3 };
        string listResult = numbers switch {
            [1, 2, 3] => "Exactly [1,2,3]",
            [1, _, 3] => "Starts with 1, ends with 3",
            [_, _, _] => "Three elements",
            _ => "Other"
        };
        Console.WriteLine(listResult);
    }
}
Advanced
99. How to use Multithreading with Tasks and PLINQ in C#?

Task and Task<T> enable asynchronous programming. PLINQ (AsParallel()) provides parallel LINQ queries. Parallel.For and Parallel.ForEach handle parallel loops.

  • Task.Run() — run on thread pool
  • Task.WhenAll() — wait for multiple
  • AsParallel() — parallel LINQ queries
  • CancellationToken — graceful cancellation
csharp
// Multithreading with Tasks and Parallel LINQ
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

class Program {
    static async Task Main() {
        // Parallel sum using tasks
        int[] arr = Enumerable.Repeat(1, 1000000).ToArray();
        long total = await ParallelSum(arr, 0, arr.Length);
        Console.WriteLine("Parallel sum: " + total);

        // Multiple async tasks
        var tasks = new List<Task<string>>();
        for (int i = 1; i <= 3; i++) {
            int id = i;
            tasks.Add(FetchDataAsync(id));
        }
        var results = await Task.WhenAll(tasks);
        Console.WriteLine("Results: " + string.Join(", ", results));

        // PLINQ
        var numbers = Enumerable.Range(1, 100);
        var squares = numbers.AsParallel()
            .Select(n => n * n)
            .ToList();
        Console.WriteLine("First 5 squares: " + string.Join(", ", squares.Take(5)));

        // Parallel.For with cancellation
        var cts = new CancellationTokenSource();
        cts.CancelAfter(500);

        try {
            Parallel.For(0, 10, new ParallelOptions { CancellationToken = cts.Token }, i => {
                Thread.Sleep(100);
                Console.WriteLine("Task " + i + " on thread " + Thread.CurrentThread.ManagedThreadId);
            });
        } catch (OperationCanceledException) {
            Console.WriteLine("Parallel.For cancelled!");
        }

        // Parallel.ForEach
        var items = Enumerable.Range(1, 20);
        Parallel.ForEach(items, item => {
            Thread.Sleep(50);
            Console.WriteLine("Processed " + item);
        });
    }

    static async Task<long> ParallelSum(int[] arr, int l, int r) {
        if (r - l <= 100000) {
            return arr.Skip(l).Take(r - l).Sum(x => (long)x);
        }
        int mid = (l + r) / 2;
        var left = ParallelSum(arr, l, mid);
        var right = ParallelSum(arr, mid, r);
        return await left + await right;
    }

    static async Task<string> FetchDataAsync(int id) {
        await Task.Delay(100);
        return "Data from source " + id;
    }
}
Advanced
100. How to build a Complete Library Management System in C#?

A Library Management System demonstrates comprehensive C# OOP: multiple classes, Dictionary for O(1) lookups, exception handling, and formatted output — all working together.

  • Dictionary<string, Book> for O(1) ISBN lookup
  • Full CRUD — add, remove, borrow, return, search, display
  • String interpolation for clean console output
  • LINQ for sorting and searching
csharp
// Complete Library Management System in C#
using System;
using System.Collections.Generic;
using System.Linq;

class Book {
    public string ISBN { get; }
    public string Title { get; }
    public string Author { get; }
    public string Genre { get; }
    public int Year { get; }
    public int TotalCopies { get; private set; }
    public int AvailableCopies { get; private set; }

    public Book(string isbn, string title, string author,
                string genre, int year, int copies = 1) {
        ISBN = isbn;
        Title = title;
        Author = author;
        Genre = genre;
        Year = year;
        TotalCopies = copies;
        AvailableCopies = copies;
    }

    public bool IsAvailable => AvailableCopies > 0;

    public void Checkout() {
        if (IsAvailable) AvailableCopies--;
    }

    public void Return() {
        if (AvailableCopies < TotalCopies) AvailableCopies++;
    }

    public void Display() {
        Console.WriteLine(ISBN.PadRight(15) + " " + Title.PadRight(30) + " " + Author.PadRight(20) + " " + Genre.PadRight(12) + " " + Year.ToString().PadRight(6) + " [" + AvailableCopies + "/" + TotalCopies + "]");
    }
}

class Member {
    private static int _nextId = 1;
    public string Id { get; }
    public string Name { get; }
    public string Email { get; }
    private List<string> _borrowedISBNs = new List<string>();
    private const int MAX_BORROW = 5;

    public Member(string name, string email) {
        Id = "M" + (_nextId++).ToString("D3");
        Name = name;
        Email = email;
    }

    public bool CanBorrow => _borrowedISBNs.Count < MAX_BORROW;

    public void Borrow(string isbn) => _borrowedISBNs.Add(isbn);

    public void Return(string isbn) => _borrowedISBNs.Remove(isbn);

    public bool HasBorrowed(string isbn) => _borrowedISBNs.Contains(isbn);

    public void Display() {
        Console.WriteLine("Member [" + Id + "] " + Name + " | Email: " + Email + " | Borrowed: " + _borrowedISBNs.Count + "/" + MAX_BORROW);
        if (_borrowedISBNs.Any())
            Console.WriteLine("  Books: " + string.Join(", ", _borrowedISBNs));
    }
}

class Library {
    private string _name;
    private Dictionary<string, Book> _books = new Dictionary<string, Book>();
    private Dictionary<string, Member> _members = new Dictionary<string, Member>();

    public Library(string name) => _name = name;

    public void AddBook(Book book) {
        _books[book.ISBN] = book;
        Console.WriteLine("Book added: " + book.Title);
    }

    public void RegisterMember(Member member) {
        _members[member.Id] = member;
        Console.WriteLine("Member registered: " + member.Name);
    }

    public void BorrowBook(string memberId, string isbn) {
        var member = GetMember(memberId);
        var book = GetBook(isbn);

        if (!member.CanBorrow)
            throw new InvalidOperationException(member.Name + " has reached borrow limit");
        if (!book.IsAvailable)
            throw new InvalidOperationException("Book not available: " + book.Title);

        book.Checkout();
        member.Borrow(isbn);
        Console.WriteLine(member.Name + " borrowed: " + book.Title);
    }

    public void ReturnBook(string memberId, string isbn) {
        var member = GetMember(memberId);
        var book = GetBook(isbn);

        if (!member.HasBorrowed(isbn))
            throw new InvalidOperationException(member.Name + " did not borrow this book");

        book.Return();
        member.Return(isbn);
        Console.WriteLine(member.Name + " returned: " + book.Title);
    }

    public List<Book> SearchByAuthor(string author) =>
        _books.Values.Where(b => b.Author.Contains(author)).ToList();

    public List<Book> SearchByGenre(string genre) =>
        _books.Values.Where(b => b.Genre == genre).ToList();

    public void DisplayAllBooks() {
        Console.WriteLine("\n=== " + _name + " - Catalog ===");
        Console.WriteLine("ISBN".PadRight(15) + "Title".PadRight(30) + "Author".PadRight(20) + "Genre".PadRight(12) + "Year".PadRight(6) + "Copies");
        Console.WriteLine(new string('-', 90));
        foreach (var book in _books.Values.OrderBy(b => b.Title))
            book.Display();
    }

    public void DisplayAllMembers() {
        Console.WriteLine("\n=== " + _name + " - Members ===");
        foreach (var member in _members.Values)
            member.Display();
    }

    public void DisplayStats() {
        int total = _books.Count;
        int available = _books.Values.Count(b => b.IsAvailable);
        Console.WriteLine("\n=== Stats ===");
        Console.WriteLine("Total books: " + total);
        Console.WriteLine("Available: " + available);
        Console.WriteLine("Checked out: " + (total - available));
        Console.WriteLine("Total members: " + _members.Count);
    }

    private Book GetBook(string isbn) {
        if (!_books.TryGetValue(isbn, out var book))
            throw new KeyNotFoundException("Book not found: " + isbn);
        return book;
    }

    private Member GetMember(string id) {
        if (!_members.TryGetValue(id, out var member))
            throw new KeyNotFoundException("Member not found: " + id);
        return member;
    }
}

class Program {
    static void Main() {
        Library lib = new Library("C# City Library");

        // Add books
        lib.AddBook(new Book("978-0", "The C# Book", "Anders Hejlsberg", "Programming", 2020, 3));
        lib.AddBook(new Book("978-1", "Design Patterns", "Gang of Four", "Programming", 2015, 2));
        lib.AddBook(new Book("978-2", "Clean Code", "Robert Martin", "Programming", 2008, 4));
        lib.AddBook(new Book("978-3", "Dune", "Frank Herbert", "Sci-Fi", 1965, 2));
        lib.AddBook(new Book("978-4", "1984", "George Orwell", "Fiction", 1949, 3));

        // Register members
        lib.RegisterMember(new Member("Alice Johnson", "alice@email.com"));
        lib.RegisterMember(new Member("Bob Smith", "bob@email.com"));
        lib.RegisterMember(new Member("Carol White", "carol@email.com"));

        lib.DisplayAllBooks();

        // Borrow books
        lib.BorrowBook("M001", "978-0");
        lib.BorrowBook("M001", "978-2");
        lib.BorrowBook("M002", "978-1");
        lib.BorrowBook("M003", "978-3");

        try {
            lib.BorrowBook("M001", "978-9");
        } catch (KeyNotFoundException e) {
            Console.WriteLine("Error: " + e.Message);
        }

        lib.ReturnBook("M001", "978-0");
        lib.BorrowBook("M002", "978-0");

        Console.WriteLine("\nSearch by genre 'Programming':");
        foreach (var book in lib.SearchByGenre("Programming"))
            book.Display();

        lib.DisplayAllMembers();
        lib.DisplayStats();
    }
}