If you're starting DSA, learn when to use each structure before memorizing code.
arr = [10, 20, 30]
arr.append(40) # add end
first = arr[0] # O(1) accessconst arr = [10, 20, 30];
arr.push(40);
const first = arr[0];import java.util.*;
List<Integer> arr = new ArrayList<>(List.of(10, 20, 30));
arr.add(40);
int first = arr.get(0);class Node:
def __init__(self, v, nxt=None):
self.v, self.next = v, nxt
head = Node(1, Node(2, Node(3)))class Node {
constructor(v, next = null) { this.v = v; this.next = next; }
}
const head = new Node(1, new Node(2, new Node(3)));class Node {
int v; Node next;
Node(int v, Node next) { this.v = v; this.next = next; }
}
Node head = new Node(1, new Node(2, new Node(3, null)));st = []
st.append(5) # push
top = st.pop() # popconst st = [];
st.push(5);
const top = st.pop();Deque<Integer> st = new ArrayDeque<>();
st.push(5);
int top = st.pop();from collections import deque
q = deque([1, 2])
q.append(3)
front = q.popleft()const q = [1, 2];
q.push(3);
const front = q.shift();Queue<Integer> q = new ArrayDeque<>();
q.offer(1); q.offer(2); q.offer(3);
int front = q.poll();freq = {}
for x in [1,2,2]:
freq[x] = freq.get(x, 0) + 1const freq = new Map();
[1,2,2].forEach(x => freq.set(x, (freq.get(x) ?? 0) + 1));Map<Integer, Integer> freq = new HashMap<>();
for (int x : new int[]{1,2,2}) {
freq.put(x, freq.getOrDefault(x, 0) + 1);
}seen = set([1, 2])
seen.add(3)
has_two = 2 in seenconst seen = new Set([1, 2]);
seen.add(3);
const hasTwo = seen.has(2);Set<Integer> seen = new HashSet<>(List.of(1, 2));
seen.add(3);
boolean hasTwo = seen.contains(2);class TreeNode:
def __init__(self, v, l=None, r=None):
self.v, self.left, self.right = v, l, r
root = TreeNode(2, TreeNode(1), TreeNode(3))class TreeNode {
constructor(v, left = null, right = null) {
this.v = v; this.left = left; this.right = right;
}
}
const root = new TreeNode(2, new TreeNode(1), new TreeNode(3));class TreeNode {
int v; TreeNode left, right;
TreeNode(int v, TreeNode l, TreeNode r) { this.v = v; this.left = l; this.right = r; }
}
TreeNode root = new TreeNode(2, new TreeNode(1, null, null), new TreeNode(3, null, null));import heapq
h = []
heapq.heappush(h, 5)
heapq.heappush(h, 1)
mn = heapq.heappop(h) # 1// JS has no built-in heap; use a library or custom class for production.
// Concept: keep smallest element at index 0.PriorityQueue<Integer> pq = new PriorityQueue<>();
pq.offer(5); pq.offer(1);
int mn = pq.poll(); // 1g = {1: [2,3], 2: [1], 3: [1]}const g = new Map([[1, [2,3]], [2, [1]], [3, [1]]]);Map<Integer, List<Integer>> g = new HashMap<>();
g.put(1, Arrays.asList(2,3));
g.put(2, Arrays.asList(1));
g.put(3, Arrays.asList(1));# fixed-size window max sum
arr, k = [2,1,5,1,3,2], 3
win = sum(arr[:k]); best = win
for i in range(k, len(arr)):
win += arr[i] - arr[i-k]
best = max(best, win)Common pitfalls: off-by-one, duplicate handling, missing empty/single-element edge cases.
Arrays store elements in contiguous memory — O(1) access, O(n) insert/delete in middle.
| Op | Array |
|---|---|
| Access | O(1) |
| Search | O(n) |
| Insert end | O(1) amortized |
| Insert mid | O(n) |
| Delete | O(n) |
Eliminates nested loops. Move pointers inward or in same direction.
def two_sum_sorted(arr, target):
l, r = 0, len(arr) - 1
while l < r:
s = arr[l] + arr[r]
if s == target: return [l, r]
elif s < target: l += 1
else: r -= 1
return []
# 3Sum: sort, fix one, two-pointer rest
def three_sum(nums):
nums.sort(); res = []
for i, v in enumerate(nums):
if i > 0 and v == nums[i-1]: continue
l, r = i+1, len(nums)-1
while l < r:
s = v + nums[l] + nums[r]
if s == 0: res.append([v,nums[l],nums[r]]); l+=1
elif s < 0: l += 1
else: r -= 1
return resMaintain a window; expand right, shrink left based on a constraint.
def longest_no_repeat(s):
seen = {}; l = res = 0
for r, ch in enumerate(s):
if ch in seen and seen[ch] >= l:
l = seen[ch] + 1
seen[ch] = r
res = max(res, r - l + 1)
return res
def max_sum_k(arr, k):
win = sum(arr[:k]); best = win
for i in range(k, len(arr)):
win += arr[i] - arr[i-k]
best = max(best, win)
return bestPrecompute for O(1) range queries. Essential for subarray sum problems.
def build_prefix(arr):
pre = [0] * (len(arr)+1)
for i,v in enumerate(arr): pre[i+1] = pre[i]+v
return pre
# Range sum [l,r] = pre[r+1] - pre[l]
# Subarray sum equals k:
def subarray_sum(nums, k):
count = 0; cur = 0; seen = {0:1}
for n in nums:
cur += n
count += seen.get(cur-k, 0)
seen[cur] = seen.get(cur,0)+1
return countMax subarray in O(n). Reset when running sum goes negative.
def max_subarray(nums):
cur = best = nums[0]
for n in nums[1:]:
cur = max(n, cur+n)
best = max(best, cur)
return bestKey heuristics: