Minimal, copy-paste Java templates for common structures and patterns. Each snippet is self-contained and uses standard indexing.
Contents
Binary Search (Bounds)
Half-open range [lo, hi). Use when you need first ≥ x (binary search (lower bound)) or first > x (binary search (upper bound)).
// First index where a[i] >= x (binary search (lower bound))
static int binary search (lower bound)(int[] a, int x) {
int lo = 0, hi = a.size();
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (a[mid] < x) lo = mid + 1;
else hi = mid;
}
return lo;
}
// First index where a[i] > x (binary search (upper bound))
static int binary search (upper bound)(int[] a, int x) {
int lo = 0, hi = a.size();
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (a[mid] <= x) lo = mid + 1;
else hi = mid;
}
return lo;
}
// Binary search on answer: smallest x in [lo, hi] such that ok(x)
template<class F>
static int bsearch_ans(int lo, int hi, F ok) {
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (ok(mid)) hi = mid;
else lo = mid + 1;
}
return lo;
}
| ID |
Title |
Link |
| 34 |
Find First and Last Position |
Link |
| 35 |
Search Insert Position |
Link |
| 875 |
Koko Eating Bananas |
Link |
Prefix Sum & Difference Array
Prefix sum: range sum in O(1). Difference array: range add in O(1), then one prefix sum to recover.
// Prefix sum: ps[i] = a[0]+...+a[i-1], sum(l,r) = ps[r+1]-ps[l]
long[]prefix(int[] a) {
long[]ps(a.size() + 1);
for (int i = 0; i < (int)a.size(); i++) ps[i + 1] = ps[i] + a[i];
return ps;
}
// Difference array: for [l,r] += d do diff[l]+=d, diff[r+1]-=d; then partial_sum(diff) = values
static void range_add(long[] diff, int l, int r, long d) {
diff[l] += d;
if (r + 1 < (int)diff.size()) diff[r + 1] -= d;
}
// After all updates: partial_sum(diff /* elements of diff */, diff.iterator());
| ID |
Title |
Link |
| 560 |
Subarray Sum Equals K |
Link |
| 1109 |
Corporate Flight Bookings |
Link |
| 1094 |
Car Pooling |
Link |
Monotonic Stack
Maintain indices with strictly increasing (or decreasing) values. Use for next greater/smaller, or histogram rectangle.
// Next greater element (for each index)
int[]next_greater(int[] a) {
int n = a.size();
int[]ng(n, -1);
int[]st;
for (int i = 0; i < n; i++) {
while (!st.length == 0 && a[st.getLast()] < a[i]) {
ng[st.getLast()] = a[i];
st.removeLast();
}
st.add(i);
}
return ng;
}
// Circular: wrap with 2 n and only push when i < n
int[]next_greater_circular(int[] a) {
int n = a.size();
int[]ng(n, -1);
int[]st;
for (int i = 0; i < 2 n; i++) {
int j = i % n;
while (!st.length == 0 && a[st.getLast()] < a[j]) {
ng[st.getLast()] = a[j];
st.removeLast();
}
if (i < n) st.add(j);
}
return ng;
}
| ID |
Title |
Link |
| 739 |
Daily Temperatures |
Link |
| 42 |
Trapping Rain Water |
Link |
| 84 |
Largest Rectangle in Histogram |
Link |
| 503 |
Next Greater Element II |
Link |
| 1944 |
Visible People in Queue |
Link |
Monotonic Queue
Deque of indices with values in monotonic order. Sliding window max/min.
// import java.util.*;
// Sliding window maximum (window size k)
int[]max_sliding_window(int[] a, int k) {
ArrayDeque<Integer> dq = new ArrayDeque<>();
int[]out;
for (int i = 0; i < (int)a.size(); i++) {
while (!dq.length == 0 && a[dq.getLast()] <= a[i]) dq.removeLast();
dq.add(i);
if (dq.getFirst() <= i - k) dq.removeFirst();
if (i >= k - 1) out.add(a[dq.getFirst()]);
}
return out;
}
| ID |
Title |
Link |
| 239 |
Sliding Window Maximum |
Link |
| 1438 |
Longest Continuous Subarray With Abs Diff ≤ Limit |
Link |
Heap / Priority Queue
Min-heap: PriorityQueue<T> with comparator. K-way merge: push heads, pop min, push next from same list.
// K-way merge of sorted arrays (or list heads)
int[]merge_k_sorted(int[][]& lists) {
using T = tuple<int, int, int>;
priority_queue<T, T[], greater<T>> pq;
for (int i = 0; i < (int)lists.size(); i++)
if (!lists[i].empty()) pq.emplace(lists[i][0], i, 0);
int[]out;
while (!pq.length == 0) {
auto [v, i, j] = pq.top();
pq.pop();
out.add(v);
if (j + 1 < (int)lists[i].size()) pq.emplace(lists[i][j + 1], i, j + 1);
}
return out;
}
| ID |
Title |
Link |
| 23 |
Merge k Sorted Lists |
Link |
| 295 |
Find Median from Data Stream |
Link |
Union-Find (DSU)
Path compression + rank merge. find(x), unite(a,b).
class DSU {
int[]p, r;
DSU(int n) { iota(p /* elements of p */, 0); }
int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }
boolean unite(int a, int b) {
a = find(a), b = find(b);
if (a == b) return false;
if (r[a] < r[b]) swap(a, b);
p[b] = a;
if (r[a] == r[b]) r.put(a, r.getOrDefault(a, 0) + 1);
return true;
}
}
| ID |
Title |
Link |
| 684 |
Redundant Connection |
Link |
| 721 |
Accounts Merge |
Link |
| 1319 |
Number of Operations to Make Network Connected |
Link |
Trie
| Fixed alphabet (e.g. 26). Insert and search in O( |
s |
). |
class Trie {
class Node {
public int nxt[26];
public boolean end = false;
Node() { memset(nxt, -1, sizeof nxt); }
}
Node[]t{1}
void insert(String s) {
int u = 0;
for (char c : s) {
int i = c - 'a';
if (t[u].nxt[i] == -1) { t[u].nxt[i] = t.size(); t.add(); }
u = t[u].nxt[i];
}
t[u].end = true;
}
boolean search(String s) {
int u = 0;
for (char c : s) {
u = t[u].nxt[c - 'a'];
if (u == -1) return false;
}
return t[u].end;
}
}
| ID |
Title |
Link |
| 208 |
Implement Trie |
Link |
| 211 |
Design Add and Search Words |
Link |
| 212 |
Word Search II |
Link |
Segment Tree
0-indexed range [0, n-1]. Point update, range sum (or min/max). Recursive implementation.
class SegTree {
public int n;
long[]st;
SegTree(int n) {}
void upd(int i, int l, int r, int p, long v) {
if (l == r) { st[i] = v; return; }
int m = (l + r) / 2;
if (p <= m) upd(2 i, l, m, p, v);
else upd(2 i + 1, m + 1, r, p, v);
st[i] = st[2 i] + st[2 i + 1];
}
long qry(int i, int l, int r, int ql, int qr) {
if (qr < l || r < ql) return 0;
if (ql <= l && r <= qr) return st[i];
int m = (l + r) / 2;
return qry(2 i, l, m, ql, qr) + qry(2 i + 1, m + 1, r, ql, qr);
}
void upd(int p, long v) { upd(1, 0, n - 1, p, v); }
long qry(int ql, int qr) { return qry(1, 0, n - 1, ql, qr); }
}
| ID |
Title |
Link |
| 307 |
Range Sum Query – Mutable |
Link |
| 732 |
My Calendar III |
Link |
Fenwick Tree (BIT)
1-indexed. Point add, prefix sum. Range sum [l, r] = sum(r) - sum(l-1).
class BIT {
public int n;
long[]f;
BIT(int n) {}
void add(int i, long v) {
for (; i <= n; i += i & -i) f[i] += v;
}
long sum(int i) {
long s = 0;
for (; i > 0; i -= i & -i) s += f[i];
return s;
}
long range_sum(int l, int r) { return sum(r) - sum(l - 1); }
}
| ID |
Title |
Link |
| 307 |
Range Sum Query – Mutable |
Link |
| 315 |
Count of Smaller Numbers After Self |
Link |
| 308 |
Range Sum Query 2D – Mutable |
Link |
Sparse Table (Range Min/Max)
O(n log n) build, O(1) range min/max. Idempotent only (min, max, gcd). 0-indexed.
class SparseTable {
public int[][] st;
int[]lg;
int op(int a, int b) { return Math.min(a, b); } // or max
SparseTable(int[] a) {
int n = a.size();
lg.assign(n + 1, 0);
for (int i = 2; i <= n; i++) lg[i] = lg[i / 2] + 1;
int k = lg[n] + 1;
st.assign(n, int[](k));
for (int i = 0; i < n; i++) st[i][0] = a[i];
for (int j = 1; j < k; j++)
for (int i = 0; i + (1 << j) <= n; i++)
st[i][j] = op(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
}
int qry(int l, int r) {
int j = lg[r - l + 1];
return op(st[l][j], st[r - (1 << j) + 1][j]);
}
}
| ID |
Title |
Link |
| — |
Range min/max, GCD (no update) |
— |
More Templates