Menu

Earn Premium with Referrals

Invite your friends and earn Premium rewards through our referral program.

See how it works and start inviting friends.

Ordered Data Structures
DSA

Ordered Data Structures

Explore data structures that maintain elements in sorted or ordered form for efficient queries and updates.

Some problems need more than a hashmap: “give me the smallest key ≥ x”, “count elements less than x”, “iterate in order”.

That’s the job of ordered containers — balanced BSTs under the hood, O(log n) per operation.

Focus on recognizing:

floor/ceiling/rank/in-order iteration = ordered map or sorted set


The Idiom Per Language

The invariant underneath every ordered structure — insert without ever breaking sort order:

Ordered Insert (Binary Search)

Insert a key into a sorted array keeping it sorted.

Binary-search the insertion point (upper_bound) in O(log n), then shift the tail right by one and write the key. This bisect idiom underlies ordered sets/maps and lower_bound/upper_bound.

ARRAY VISUALIZER
Steps
3
0
9
1
15
2
31
3
·
4
Press ▶ to animate, or step through manually.
Variables
keys: ← → space F
Pseudocode

                        1
                        pos = upper_bound(sorted, key)
                      
                        2
                          # first index with value > key
                      
                        3
                        shift elements [pos..end] right by 1
                      
                        4
                        sorted[pos] = key
                      
                        5
                        # lookups stay O(log n), inserts O(n)
                      
TreeMap<Integer, String> map = new TreeMap<>();

map.put(10, "a");
map.floorKey(7);     // greatest key ≤ 7   (null if none)
map.ceilingKey(7);   // smallest key ≥ 7
map.lowerKey(7);     // strictly below
map.higherKey(7);    // strictly above

TreeSet<Integer> set = new TreeSet<>();
set.floor(7); set.ceiling(7);
from sortedcontainers import SortedList

sl = SortedList([10])
sl.add(5)

i = sl.bisect_right(7) - 1   # index of greatest element ≤ 7
floor = sl[i] if i >= 0 else None

j = sl.bisect_left(7)        # index of smallest element ≥ 7
ceiling = sl[j] if j < len(sl) else None

# stdlib fallback: bisect over a plain sorted list
std::map<int, std::string> m;
m[10] = "a";

auto it = m.lower_bound(7);      // first key ≥ 7
if (it != m.begin())
    auto floorIt = std::prev(it); // greatest key < 7 (careful at begin)

m.upper_bound(7);                // first key > 7

std::set<int> s;                 // same member functions
// No native sorted map. Keep a sorted array + binary search:
function floor(arr, x) {           // greatest element ≤ x
  let lo = 0,
    hi = arr.length - 1,
    ans = null;
  while (lo <= hi) {
    const mid = (lo + hi) >> 1;
    if (arr[mid] <= x) {
      ans = arr[mid];
      lo = mid + 1;
    } else hi = mid - 1;
  }
  return ans;
}

// insert keeps order: O(n) via splice — fine at interview scale.
// For heavy workloads: segment tree / Fenwick over value ranges.

Pattern: Sliding Window Median

Classic consumer of ordered structures — keep the window’s contents in a sorted container; median is a rank lookup:

insert outgoing element's removal + incoming element each step
median = element at rank ⌊k/2⌋   → O(log n) per step

Same skeleton works with two heaps (see Heap section) — but the ordered-container version generalizes to any percentile.

Ordered structure = hashmap’s operations + rank/neighbor queries.


Common Mistakes

Using a hashmap then sorting per query.

Sorting on every query is O(n log n). If queries repeat, maintain order incrementally.


Off-by-one between bisect_left and bisect_right.

bisect_left → first ≥ x · bisect_right − 1 → last ≤ x. Mixing them silently skips duplicates.


C++ prev(begin()).

Calling prev before checking it != begin() is undefined behavior — guard the boundary.


Complexity

OperationTime
insert / deleteO(log n)
floor / ceilingO(log n)
in-order iterationO(n) total
JS sorted-array insertO(n)

My Private Notes

Notes are auto-saved locally to this device.