Consider a situation where we have a set of intervals and we need the following operations to be implemented efficiently:
- Add an interval
- Remove an interval
- Given an interval x, find if x overlaps with any of the existing intervals.
An Interval Tree can be implemented as an augmented binary-search tree (preferably self-balancing), and thus enable us to perform the required operations in O(logN) time complexity.
Each node of the tree will store the following information:
- An interval i: represented as a pair [low, high].
- Metadata max of right-endpoints: The maximum of the right-endpoints of all the intervals stored in the subtree rooted at this node. Storing this metadata is how we are augmenting the tree.
Example Interval Tree used in Interval Tree | Set 1:

In Interval Tree | Set 1, we saw how to implement an interval tree using a simple BST (which is not self-balancing). In this article, we will use the built-in GNU tree-based container to implement an Interval Tree. The benefits of doing so are:
- We do not have to code our own tree data structure.
- We get the default operations like insert and delete out-of-the-box.
- We get to use the in-built Red-Black tree implementation, which means our tree will be self-balancing.
We will be using GNU policy-based implementation of tree data structure.
The article Policy-based data structures in g++ introduce GNU policy-based data structure along with the required header files.
We will define our own Node_update policy such that we can maintain the maximum of right-endpoints of intervals in the subtree as metadata in the nodes of our tree.
The syntax for defining a custom Node_policy is:
C++
#include <iostream> // Include the iostream header for cout and endl
#include <functional> // For std::function
// Define a custom node update policy struct
template <
typename Const_Node_Iterator, // Constant node iterator type
typename Node_Iterator, // Node iterator type
typename Cmp_Fn_, // Comparator function type
typename Allocator_> // Allocator type
struct custom_node_update_policy {
// Define a nested struct to represent metadata type
struct metadata_type {
// Define members of metadata type here
};
// Define a method similar to the apply() method in Java
void apply(Node_Iterator it,
Const_Node_Iterator endIt)
{
// Implementation of the method
// Note: C++ doesn't have function objects like Java
}
// Other methods can be added here as needed
};
using std::cout; // Import cout into the global namespace
using std::endl; // Import endl into the global namespace
int main() {
// Your program logic goes here
// You can create instances of
// custom_node_update_policy and call its methods
// For example:
custom_node_update_policy<int, int,
std::function<int(int)>,
void*> policy;
policy.apply(10, 20); // Example call to apply method
// Output to demonstrate that the program is running
cout << "Program executed successfully." << endl;
return 0;
}
Java
import java.util.function.Function;
public class Program {
// Define a generic class with type parameters
public static class CustomNodeUpdatePolicy<
ConstNodeIterator, NodeIterator, CmpFn, Allocator> {
// Define a nested class to represent metadata type
public class MetadataType {
// Define members of metadata type here
}
// Define a method similar to the operator() in C++
public void apply(NodeIterator it,
ConstNodeIterator endIt)
{
// Implementation of the method
// Note: Java doesn't have operator overloading
// like C++
}
// Other methods can be added here as needed
}
public static void main(String[] args)
{
// Your program logic goes here
// You can create instances of
// CustomNodeUpdatePolicy and call its methods For
// example:
CustomNodeUpdatePolicy<Integer, Integer,
Function<Integer, Integer>,
Object> policy
= new CustomNodeUpdatePolicy<>();
policy.apply(10,
20); // Example call to apply method
// Output to demonstrate that the program is running
System.out.println(
"Program executed successfully.");
}
}
C#
using System;
public class Program
{
// Define a generic class with type parameters
public class CustomNodeUpdatePolicy<ConstNodeIterator, NodeIterator, CmpFn, Allocator>
{
// Define a nested class to represent metadata type
public class MetadataType
{
// Define members of metadata type here
}
// Define a method similar to the operator() in C++
public void Apply(NodeIterator it, ConstNodeIterator endIt)
{
// Implementation of the method
// Note: C# doesn't have operator overloading like C++
}
// Other methods can be added here as needed
}
public static void Main(string[] args)
{
// Your program logic goes here
// You can create instances of CustomNodeUpdatePolicy and call its methods
// For example:
CustomNodeUpdatePolicy<int, int, Func<int, int, int>, object> policy = new CustomNodeUpdatePolicy<int, int, Func<int, int, int>, object>();
policy.Apply(10, 20); // Example call to Apply method
// Output to demonstrate that the program is running
Console.WriteLine("Program executed successfully.");
}
}
JavaScript
// Define a generic class with type parameters
class CustomNodeUpdatePolicy {
constructor(ConstNodeIterator, NodeIterator, CmpFn, Allocator) {
this.ConstNodeIterator = ConstNodeIterator;
this.NodeIterator = NodeIterator;
this.CmpFn = CmpFn;
this.Allocator = Allocator;
}
// Define a nested class to represent metadata type
MetadataType() {
// Define members of metadata type here
}
// Define a method similar to the operator() in Python
apply(it, endIt) {
// Implementation of the method
// Note: JavaScript doesn't have operator overloading like Python
}
// Other methods can be added here as needed
}
// Your program logic goes here
// You can create instances of CustomNodeUpdatePolicy and call its methods
// For example:
const policy = new CustomNodeUpdatePolicy(Number, Number, (x, y) => x + y, Object);
policy.apply(10, 20); // Example call to Apply method
// Output to demonstrate that the program is running
console.log("Program executed successfully.");
Python3
# Define a generic class with type parameters
class CustomNodeUpdatePolicy:
def __init__(self, ConstNodeIterator, NodeIterator, CmpFn, Allocator):
self.ConstNodeIterator = ConstNodeIterator
self.NodeIterator = NodeIterator
self.CmpFn = CmpFn
self.Allocator = Allocator
# Define a nested class to represent metadata type
class MetadataType:
pass
# Define members of metadata type here
# Define a method similar to the operator() in C++
def apply(self, it, endIt):
pass
# Implementation of the method
# Note: Python doesn't have operator overloading like C++
# Other methods can be added here as needed
# Your program logic goes here
# You can create instances of CustomNodeUpdatePolicy and call its methods
# For example:
policy = CustomNodeUpdatePolicy(int, int, lambda x, y: x + y, object)
policy.apply(10, 20) # Example call to Apply method
# Output to demonstrate that the program is running
print("Program executed successfully.")
OutputProgram executed successfully.
- type_of_our_metadata: int in our case since we want to store the metadata "max of right-endpoints of intervals in the subtree".
- void operator()(node_iterator it, const_node_iterator end_it): method which is called internally to restore node-invariance, i.e. maintaining correct metadata, after invariance has been invalidated.
- it: node_iterator to the node whose invariance we need to restore.
- end_it: const_node_iterator to a just-after-leaf node.
See GNU tree-based containers for more details.
We will also define a method overlapSearch which searches for any interval in the tree overlapping with a given interval i.
// pseudocode for overlapSearch
Interval overlapSearch(Interval i) {
// start from root
it = root_node
while (it not null) {
if (doOVerlap(i, it->interval)) {
// overlap found
return it->interval
}
if (left_child exists
AND
left_child->max_right_endpoint
>= it->left_endpoint) {
// go to left child
it = it->left_child
}
else {
// go to right child
it = it->right_child
}
}
// no overlapping interval found
return NO_INTERVAL_FOUND
}
Below is the implementation of the Interval Tree:
C++
// CPP program for above approach
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef pair<int, int> Interval;
// An invalid interval, used as
// return value to denote that no
// matching interval was found
const Interval NO_INTERVAL_FOUND = { 1, 0 };
// interval update policy struct
template <class Node_CItr,
class Node_Itr,
class Cmp_Fn, class _Alloc>
struct interval_node_update_policy {
// Our metadata is maximum of
// right-endpoints of intervals in the
// sub-tree, which is of type int
typedef int metadata_type;
// An utility function to check
// if given two intervals overlap
bool doOverlap(Interval i1,
Node_CItr i2)
{
return (i1.first <= (*i2)->second
&& (*i2)->first <= i1.second);
}
// Search for any interval that
// overlaps with Interval i
Interval overlapSearch(Interval i)
{
for (Node_CItr it = node_begin();
it != node_end();) {
if (doOverlap(i, it)) {
return { (*it)->first,
(*it)->second };
}
if (it.get_l_child() != node_end()
&& it.get_l_child()
.get_metadata()
>= i.first) {
it = it.get_l_child();
}
else {
it = it.get_r_child();
}
}
return NO_INTERVAL_FOUND;
}
// To restore the node-invariance
// of the node pointed to by
// (it). We need to derive the
// metadata for node (it) from
// its left-child and right-child.
void operator()(Node_Itr it,
Node_CItr end_it)
{
int max_high = (*it)->second;
if (it.get_l_child() != end_it) {
max_high = max(
max_high,
it.get_l_child()
.get_metadata());
}
if (it.get_r_child() != end_it) {
max_high = max(
max_high,
it.get_r_child()
.get_metadata());
}
// The max of right-endpoint
// of this node and the max
// right-endpoints of children.
const_cast<int&>(
it.get_metadata())
= max_high;
}
virtual Node_CItr node_begin() const = 0;
virtual Node_CItr node_end() const = 0;
virtual ~interval_node_update_policy() {}
};
// IntervalTree data structure
// rb_tree_tag: uses red-black search tree
// interval_node_update_policy:
// our custom Node_update policy
typedef tree<Interval,
null_type,
less<Interval>,
rb_tree_tag,
interval_node_update_policy>
IntervalTree;
// Driver Code
int main()
{
IntervalTree IT;
Interval intvs[] = { { 15, 20 },
{ 10, 30 },
{ 17, 19 },
{ 5, 20 },
{ 12, 15 },
{ 30, 40 } };
for (Interval intv : intvs) {
IT.insert(intv);
}
Interval toSearch = { 25, 29 };
cout << "\nSearching for interval ["
<< toSearch.first << ", "
<< toSearch.second << "]";
Interval res = IT.overlapSearch(toSearch);
if (res == NO_INTERVAL_FOUND)
cout << "\nNo Overlapping Interval\n";
else
cout << "\nOverlaps with ["
<< res.first << ", "
<< res.second << "]\n";
Interval toErase = { 10, 30 };
IT.erase(toErase);
cout << "\nDeleting interval ["
<< toErase.first << ", "
<< toErase.second
<< "]\n";
cout << "\nSearching for interval ["
<< toSearch.first << ", "
<< toSearch.second << "]";
res = IT.overlapSearch(toSearch);
if (res == NO_INTERVAL_FOUND)
cout << "\nNo Overlapping Interval\n";
else
cout << "\nOverlaps with ["
<< res.first << ", "
<< res.second << "]\n";
return 0;
}
Java
import java.util.Comparator;
import java.util.TreeSet;
// Class to represent intervals
class Interval {
int first, second;
public Interval(int first, int second) {
this.first = first;
this.second = second;
}
}
// Class representing the Interval Tree
class IntervalTree {
TreeSet<Interval> treeSet;
// Constructor for IntervalTree class
public IntervalTree() {
// Use a TreeSet with a custom comparator based on the second endpoint of intervals
treeSet = new TreeSet<>(Comparator.comparingInt(interval -> interval.second));
}
// Method to insert an interval into the tree
public void insert(Interval interval) {
treeSet.add(interval);
}
// Method to search for any interval that overlaps with the given interval
public Interval overlapSearch(Interval interval) {
for (Interval i : treeSet) {
if (doOverlap(interval, i)) {
return new Interval(i.first, i.second);
}
}
return NO_INTERVAL_FOUND;
}
// Method to remove an interval from the tree
public void erase(Interval interval) {
treeSet.remove(interval);
}
// Helper method to check if two intervals overlap
private boolean doOverlap(Interval i1, Interval i2) {
return (i1.first <= i2.second && i2.first <= i1.second);
}
// Declare NO_INTERVAL_FOUND as static or public
public static final Interval NO_INTERVAL_FOUND = new Interval(1, 0);
}
// Main class to test the IntervalTree
public class Main {
public static void main(String[] args) {
IntervalTree IT = new IntervalTree();
Interval[] intvs = {
new Interval(15, 20),
new Interval(10, 30),
new Interval(17, 19),
new Interval(5, 20),
new Interval(12, 15),
new Interval(30, 40)
};
// Insert intervals into the tree
for (Interval intv : intvs) {
IT.insert(intv);
}
// Search for overlapping interval
Interval toSearch = new Interval(25, 29);
System.out.println("Searching for interval [" + toSearch.first + ", " + toSearch.second + "]");
Interval res = IT.overlapSearch(toSearch);
if (res == IntervalTree.NO_INTERVAL_FOUND)
System.out.println("No Overlapping Interval");
else
System.out.println("Overlaps with [" + res.first + ", " + res.second + "]");
// Remove an interval from the tree
Interval toErase = new Interval(10, 30);
IT.erase(toErase);
System.out.println("Deleting interval [" + toErase.first + ", " + toErase.second + "]");
// Search for overlapping interval after deletion
System.out.println("Searching for interval [" + toSearch.first + ", " + toSearch.second + "]");
res = IT.overlapSearch(toSearch);
if (res == IntervalTree.NO_INTERVAL_FOUND)
System.out.println("No Overlapping Interval");
else
System.out.println("Overlaps with [" + res.first + ", " + res.second + "]");
}
}
C#
using System;
using System.Collections.Generic;
// Class representing an interval
class Interval
{
public int Start { get; set; }
public int End { get; set; }
public Interval(int start, int end)
{
Start = start;
End = end;
}
}
// Class representing an Interval Tree
class IntervalTree
{
private readonly SortedSet<Interval> intervals;
public IntervalTree()
{
intervals = new SortedSet<Interval>(Comparer<Interval>.Create((a, b) => a.Start.CompareTo(b.Start)));
}
// Insert an interval into the Interval Tree
public void Insert(Interval interval)
{
intervals.Add(interval);
}
// Search for any interval that overlaps with the given query interval
public Interval OverlapSearch(Interval queryInterval)
{
foreach (var interval in intervals)
{
if (DoOverlap(queryInterval, interval))
{
return interval;
}
}
return null;
}
// Remove an interval from the Interval Tree
public void Erase(Interval interval)
{
intervals.Remove(interval);
}
// Check if two intervals overlap
private bool DoOverlap(Interval i1, Interval i2)
{
return (i1.Start <= i2.End && i2.Start <= i1.End);
}
}
class Program
{
static void Main()
{
IntervalTree intervalTree = new IntervalTree();
Interval[] intervals = {
new Interval(15, 20),
new Interval(10, 30),
new Interval(17, 19),
new Interval(5, 20),
new Interval(12, 15),
new Interval(30, 40)
};
// Insert intervals into the Interval Tree
foreach (var interval in intervals)
{
intervalTree.Insert(interval);
}
Interval toSearch = new Interval(25, 29);
Console.Write($"\nSearching for interval [{toSearch.Start}, {toSearch.End}]: ");
Interval result = intervalTree.OverlapSearch(toSearch);
if (result == null)
Console.WriteLine("No Overlapping Interval");
else
Console.WriteLine($"Overlaps with [{result.Start}, {result.End}]");
Interval toErase = new Interval(10, 30);
intervalTree.Erase(toErase);
Console.Write($"\nDeleting interval [{toErase.Start}, {toErase.End}]: ");
Console.Write($"\nSearching for interval [{toSearch.Start}, {toSearch.End}]: ");
result = intervalTree.OverlapSearch(toSearch);
if (result == null)
Console.WriteLine("No Overlapping Interval");
else
Console.WriteLine($"Overlaps with [{result.Start}, {result.End}]");
}
}
JavaScript
// JavaScript Program for the above approach
// Define a Node class representing a node in the interval tree
class Node {
constructor(interval) {
this.interval = interval;
this.max = interval[1];
this.left = null;
this.right = null;
}
}
// Define an IntervalTree class to manage the interval tree operations
class IntervalTree {
constructor() {
this.root = null;
}
// insert a new interval into the interval tree
insert(root, interval) {
if (!root) {
return new Node(interval);
}
if (interval[0] < root.interval[0]) {
root.left = this.insert(root.left, interval);
} else {
root.right = this.insert(root.right, interval);
}
root.max = Math.max(root.max, interval[1]);
return root;
}
// check for interval operlap in the interval tree
overlap(root, interval) {
if (!root) {
return null;
}
if (root.interval[0] <= interval[1] && root.interval[1] >= interval[0]) {
return root.interval;
}
if (root.left && root.left.max >= interval[0]) {
return this.overlap(root.left, interval);
}
return this.overlap(root.right, interval);
}
// delete an interval from the interval tree
delete(root, interval) {
if (!root) {
return root;
}
if (interval[0] < root.interval[0]) {
root.left = this.delete(root.left, interval);
} else if (interval[0] > root.interval[0]) {
root.right = this.delete(root.right, interval);
} else {
if (!root.left) {
let temp = root.right;
root = null;
return temp;
} else if (!root.right) {
let temp = root.left;
root = null;
return temp;
}
let temp = this.minValueNode(root.right);
root.interval = temp.interval;
root.right = this.delete(root.right, temp.interval);
}
return root;
}
// helper function to find the node with the minimum value in subtree
minValueNode(root) {
let current = root;
while (current.left !== null) {
current = current.left;
}
return current;
}
}
// Example usage of the IntervalTree
const intervals = [[15, 20], [10, 30], [17, 19], [5, 20], [12, 15], [30, 40]];
const IT = new IntervalTree();
for (const interval of intervals) {
IT.root = IT.insert(IT.root, interval);
}
// Search for an interval and print the result
const to_search = [25, 29];
console.log(`Searching for interval ${JSON.stringify(to_search)}`);
let res = IT.overlap(IT.root, to_search);
if (res) {
console.log(`Overlaps with ${JSON.stringify(res)}`);
} else {
console.log("No Overlapping Interval");
}
// Delete an interval and print the result
const to_erase = [10, 30];
console.log(`Deleting interval ${JSON.stringify(to_erase)}`);
IT.root = IT.delete(IT.root, to_erase);
// Search for an interval again after deletion and print the result
console.log(`Searching for interval ${JSON.stringify(to_search)}`);
res = IT.overlap(IT.root, to_search);
if (res) {
console.log(`Overlaps with ${JSON.stringify(resultAfterDeletion)}`);
} else {
console.log("No Overlapping Interval");
}
// This code is contributed by Yash Agarwal(yashagarwal2852002)
Python3
# Define a Node class representing a node in the interval tree
class Node:
def __init__(self, interval):
self.interval = interval
self.max = interval[1]
self.left = None
self.right = None
# Define an IntervalTree class to manage the interval tree operations
class IntervalTree:
def __init__(self):
self.root = None
# Insert a new interval into the interval tree
def insert(self, root, interval):
if not root:
return Node(interval)
if interval[0] < root.interval[0]:
root.left = self.insert(root.left, interval)
else:
root.right = self.insert(root.right, interval)
root.max = max(root.max, interval[1])
return root
# Check for interval overlap in the interval tree
def overlap(self, root, interval):
if not root:
return None
if (root.interval[0] <= interval[1] and root.interval[1] >= interval[0]):
return root.interval
if root.left and root.left.max >= interval[0]:
return self.overlap(root.left, interval)
return self.overlap(root.right, interval)
# Delete an interval from the interval tree
def delete(self, root, interval):
if not root:
return root
if interval[0] < root.interval[0]:
root.left = self.delete(root.left, interval)
elif interval[0] > root.interval[0]:
root.right = self.delete(root.right, interval)
else:
if root.left is None:
temp = root.right
root = None
return temp
elif root.right is None:
temp = root.left
root = None
return temp
temp = self.minValueNode(root.right)
root.interval = temp.interval
root.right = self.delete(root.right, temp.interval)
return root
# Helper function to find the node with the minimum value in a subtree
def minValueNode(self, root):
current = root
while(current.left is not None):
current = current.left
return current
# Example usage of the IntervalTree
intervals = [(15, 20), (10, 30), (17, 19), (5, 20), (12, 15), (30, 40)]
IT = IntervalTree()
for interval in intervals:
IT.root = IT.insert(IT.root, interval)
# Search for an interval and print the result
to_search = (25, 29)
print(f"Searching for interval {to_search}")
res = IT.overlap(IT.root, to_search)
if res:
print(f"Overlaps with {res}")
else:
print("No Overlapping Interval")
# Delete an interval and print the result
to_erase = (10, 30)
print(f"Deleting interval {to_erase}")
IT.root = IT.delete(IT.root, to_erase)
# Search for an interval again after deletion and print the result
print(f"Searching for interval {to_search}")
res = IT.overlap(IT.root, to_search)
if res:
print(f"Overlaps with {res}")
else:
print("No Overlapping Interval")
Output
Searching for interval [25, 29]
Overlaps with [10, 30]
Deleting interval [10, 30]
Searching for interval [25, 29]
No Overlapping Interval
Time Complexity : O(log N), All operations are logarithmic in size, i.e. O(logN), where N is the number of intervals stored in the tree.
Auxiliary Space: O(N)
We are able to achieve logarithmic worst-case complexity because a red-black tree is used internally which is self-balancing.
Similar Reads
Basics & Prerequisites
Data Structures
Array Data StructureIn this article, we introduce array, implementation in different popular languages, its basic operations and commonly seen problems / interview questions. An array stores items (in case of C/C++ and Java Primitive Arrays) or their references (in case of Python, JS, Java Non-Primitive) at contiguous
3 min read
String in Data StructureA string is a sequence of characters. The following facts make string an interesting data structure.Small set of elements. Unlike normal array, strings typically have smaller set of items. For example, lowercase English alphabet has only 26 characters. ASCII has only 256 characters.Strings are immut
2 min read
Hashing in Data StructureHashing is a technique used in data structures that efficiently stores and retrieves data in a way that allows for quick access. Hashing involves mapping data to a specific index in a hash table (an array of items) using a hash function. It enables fast retrieval of information based on its key. The
2 min read
Linked List Data StructureA linked list is a fundamental data structure in computer science. It mainly allows efficient insertion and deletion operations compared to arrays. Like arrays, it is also used to implement other data structures like stack, queue and deque. Hereâs the comparison of Linked List vs Arrays Linked List:
2 min read
Stack Data StructureA Stack is a linear data structure that follows a particular order in which the operations are performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). LIFO implies that the element that is inserted last, comes out first and FILO implies that the element that is inserted first
2 min read
Queue Data StructureA Queue Data Structure is a fundamental concept in computer science used for storing and managing data in a specific order. It follows the principle of "First in, First out" (FIFO), where the first element added to the queue is the first one to be removed. It is used as a buffer in computer systems
2 min read
Tree Data StructureTree Data Structure is a non-linear data structure in which a collection of elements known as nodes are connected to each other via edges such that there exists exactly one path between any two nodes. Types of TreeBinary Tree : Every node has at most two childrenTernary Tree : Every node has at most
4 min read
Graph Data StructureGraph Data Structure is a collection of nodes connected by edges. It's used to represent relationships between different entities. If you are looking for topic-wise list of problems on different topics like DFS, BFS, Topological Sort, Shortest Path, etc., please refer to Graph Algorithms. Basics of
3 min read
Trie Data StructureThe Trie data structure is a tree-like structure used for storing a dynamic set of strings. It allows for efficient retrieval and storage of keys, making it highly effective in handling large datasets. Trie supports operations such as insertion, search, deletion of keys, and prefix searches. In this
15+ min read
Algorithms
Searching AlgorithmsSearching algorithms are essential tools in computer science used to locate specific items within a collection of data. In this tutorial, we are mainly going to focus upon searching in an array. When we search an item in an array, there are two most common algorithms used based on the type of input
2 min read
Sorting AlgorithmsA Sorting Algorithm is used to rearrange a given array or list of elements in an order. For example, a given array [10, 20, 5, 2] becomes [2, 5, 10, 20] after sorting in increasing order and becomes [20, 10, 5, 2] after sorting in decreasing order. There exist different sorting algorithms for differ
3 min read
Introduction to RecursionThe process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. A recursive algorithm takes one step toward solution and then recursively call itself to further move. The algorithm stops once we reach the solution
14 min read
Greedy AlgorithmsGreedy algorithms are a class of algorithms that make locally optimal choices at each step with the hope of finding a global optimum solution. At every step of the algorithm, we make a choice that looks the best at the moment. To make the choice, we sometimes sort the array so that we can always get
3 min read
Graph AlgorithmsGraph is a non-linear data structure like tree data structure. The limitation of tree is, it can only represent hierarchical data. For situations where nodes or vertices are randomly connected with each other other, we use Graph. Example situations where we use graph data structure are, a social net
3 min read
Dynamic Programming or DPDynamic Programming is an algorithmic technique with the following properties.It is mainly an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of
3 min read
Bitwise AlgorithmsBitwise algorithms in Data Structures and Algorithms (DSA) involve manipulating individual bits of binary representations of numbers to perform operations efficiently. These algorithms utilize bitwise operators like AND, OR, XOR, NOT, Left Shift, and Right Shift.BasicsIntroduction to Bitwise Algorit
4 min read
Advanced
Segment TreeSegment Tree is a data structure that allows efficient querying and updating of intervals or segments of an array. It is particularly useful for problems involving range queries, such as finding the sum, minimum, maximum, or any other operation over a specific range of elements in an array. The tree
3 min read
Pattern SearchingPattern searching algorithms are essential tools in computer science and data processing. These algorithms are designed to efficiently find a particular pattern within a larger set of data. Patten SearchingImportant Pattern Searching Algorithms:Naive String Matching : A Simple Algorithm that works i
2 min read
GeometryGeometry is a branch of mathematics that studies the properties, measurements, and relationships of points, lines, angles, surfaces, and solids. From basic lines and angles to complex structures, it helps us understand the world around us.Geometry for Students and BeginnersThis section covers key br
2 min read
Interview Preparation
Practice Problem