A comprehensive Java cheatsheet covering data structures, utility classes, common patterns, and tricks frequently used in LeetCode problems.
Data Structures
Array
int[] arr = new int[10]; // Initialize an array of size 10 (default 0)
int[] arr = new int[]{1, 2, 3, 4, 5}; // Initialize an array with values
int len = arr.length; // Get the length of an array
int[] copy = Arrays.copyOf(arr, arr.length); // Copy an array
int[] copy = Arrays.copyOfRange(arr, 1, 3); // Copy a range [1, 3)
Arrays.sort(arr); // Sort an array in ascending order
Arrays.sort(arr, 1, 4); // Sort a range [1, 4)
Arrays.fill(arr, 0); // Fill an array with a specific value
Arrays.fill(arr, 1, 4, 0); // Fill a range [1, 4) with 0
int idx = Arrays.binarySearch(arr, 3); // Binary search (array must be sorted)
boolean eq = Arrays.equals(arr, copy); // Compare two arrays
String s = Arrays.toString(arr); // Convert array to string "[1, 2, 3]"
// 2D Array
int[][] grid = new int[3][4]; // 3 rows, 4 columns
int[][] grid = {{1,2},{3,4},{5,6}};
int rows = grid.length; // Number of rows
int cols = grid[0].length; // Number of columns
int[][] deepCopy = new int[rows][cols];
for (int i = 0; i < rows; i++)
deepCopy[i] = Arrays.copyOf(grid[i], cols);
// Sort 2D array by first element
Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
// Sort 2D array by second element
Arrays.sort(intervals, (a, b) -> a[1] - b[1]);
List (ArrayList)
List<Integer> list = new ArrayList<>();
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3)); // Init with values
List<Integer> list = new ArrayList<>(Collection); // Init from another collection
list.add(1); // Append to end — O(1)
list.add(0, 1); // Insert at index — O(n)
list.get(0); // Get element at index — O(1)
list.set(0, 10); // Set element at index — O(1)
list.remove(0); // Remove element at index — O(n)
list.remove(Integer.valueOf(1)); // Remove first occurrence of value
list.contains(1); // Check if element exists — O(n)
list.indexOf(1); // First index of element, -1 if not found
list.size(); // Get the size
list.isEmpty(); // Check if empty
list.clear(); // Remove all elements
Collections.sort(list); // Sort in ascending order
Collections.sort(list, Collections.reverseOrder()); // Sort in descending order
list.sort((a, b) -> a - b); // Sort with custom comparator
Collections.reverse(list); // Reverse the list
Collections.swap(list, 0, 1); // Swap two elements
int[] arr = list.stream().mapToInt(i -> i).toArray(); // List<Integer> → int[]
List<Integer> list = Arrays.stream(arr).boxed().collect(Collectors.toList()); // int[] → List<Integer>
// Sublist (returns a view, not a copy)
List<Integer> sub = list.subList(1, 3); // [1, 3)
LinkedList
LinkedList<Integer> ll = new LinkedList<>();
ll.addFirst(1); // Add to head — O(1)
ll.addLast(2); // Add to tail — O(1)
ll.getFirst(); // Get head element — O(1)
ll.getLast(); // Get tail element — O(1)
ll.removeFirst(); // Remove and return head — O(1)
ll.removeLast(); // Remove and return tail — O(1)
// LinkedList also implements Queue and Deque interfaces
Queue
Queue<Integer> queue = new LinkedList<>();
queue.offer(1); // Add an element to the queue (tail) — O(1)
queue.poll(); // Remove and return the head of the queue — O(1)
queue.peek(); // Return the head of the queue — O(1)
queue.size(); // Get the size of the queue
queue.isEmpty(); // Check if the queue is empty
Deque (Double-ended Queue)
Deque<Integer> deque = new ArrayDeque<>(); // Preferred over Stack and LinkedList
deque.offerFirst(1); // Add to front — O(1)
deque.offerLast(2); // Add to back — O(1)
deque.pollFirst(); // Remove and return front — O(1)
deque.pollLast(); // Remove and return back — O(1)
deque.peekFirst(); // Return front — O(1)
deque.peekLast(); // Return back — O(1)
deque.size();
deque.isEmpty();
// Use Deque as Stack (preferred over Stack class)
Deque<Integer> stack = new ArrayDeque<>();
stack.push(1); // Push to top (front)
stack.pop(); // Pop from top (front)
stack.peek(); // Peek top (front)
Stack
Stack<Integer> stack = new Stack<>(); // Legacy class, prefer ArrayDeque
stack.push(1); // Push an element to the stack
stack.pop(); // Pop and return the top of the stack
stack.peek(); // Return the top of the stack
stack.size(); // Get the size of the stack
stack.isEmpty(); // Check if the stack is empty
Set
// HashSet — unordered, O(1) operations
Set<Integer> set = new HashSet<>();
Set<Integer> set = new HashSet<>(Arrays.asList(1, 2, 3));
set.add(1); // Add an element — O(1)
set.contains(1); // Check if an element exists — O(1)
set.remove(1); // Remove an element — O(1)
set.size(); // Get the size
set.clear(); // Clear all elements
// LinkedHashSet — maintains insertion order
Set<Integer> set = new LinkedHashSet<>();
// TreeSet — sorted, O(log n) operations
TreeSet<Integer> treeSet = new TreeSet<>();
treeSet.add(5); treeSet.add(1); treeSet.add(3);
treeSet.first(); // Smallest element — O(log n)
treeSet.last(); // Largest element — O(log n)
treeSet.lower(3); // Greatest element strictly less than 3 → 1
treeSet.higher(3); // Smallest element strictly greater than 3 → 5
treeSet.floor(3); // Greatest element ≤ 3 → 3
treeSet.ceiling(3); // Smallest element ≥ 3 → 3
treeSet.headSet(3); // Elements < 3 (view)
treeSet.tailSet(3); // Elements ≥ 3 (view)
treeSet.subSet(1, 5); // Elements in [1, 5) (view)
// Iterate over set
for (int val : set) { ... }
Map
// HashMap — unordered, O(1) operations
Map<Integer, String> map = new HashMap<>();
map.put(1, "One"); // Put a key-value pair — O(1)
map.get(1); // Get value by key, null if not found — O(1)
map.getOrDefault(1, "Default"); // Get value with default
map.containsKey(1); // Check if key exists — O(1)
map.containsValue("One"); // Check if value exists — O(n)
map.remove(1); // Remove a key-value pair — O(1)
map.size(); // Get the size
map.clear(); // Clear all
// Useful methods for LeetCode
map.putIfAbsent(1, "One"); // Put only if key doesn't exist
map.merge(1, 1, Integer::sum); // Increment counter pattern
map.computeIfAbsent(1, k -> new ArrayList<>()); // Lazy initialization
// Frequency counter pattern
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
// Or using merge
for (int num : nums) {
map.merge(num, 1, Integer::sum);
}
// Iterate over map
for (Map.Entry<Integer, String> entry : map.entrySet()) {
int key = entry.getKey();
String value = entry.getValue();
}
for (int key : map.keySet()) { ... }
for (String value : map.values()) { ... }
// LinkedHashMap — maintains insertion order
Map<Integer, String> map = new LinkedHashMap<>();
// TreeMap — sorted by key, O(log n) operations
TreeMap<Integer, String> treeMap = new TreeMap<>();
treeMap.firstKey(); // Smallest key
treeMap.lastKey(); // Largest key
treeMap.lowerKey(3); // Greatest key strictly less than 3
treeMap.higherKey(3); // Smallest key strictly greater than 3
treeMap.floorKey(3); // Greatest key ≤ 3
treeMap.ceilingKey(3); // Smallest key ≥ 3
treeMap.firstEntry(); // Entry with smallest key
treeMap.lastEntry(); // Entry with largest key
treeMap.pollFirstEntry(); // Remove and return entry with smallest key
treeMap.pollLastEntry(); // Remove and return entry with largest key
Priority Queue / Heap
PriorityQueue<Integer> pq = new PriorityQueue<>(); // Min heap (default)
PriorityQueue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder()); // Max heap
PriorityQueue<Integer> pq = new PriorityQueue<>(Arrays.asList(1, 2, 3)); // Init with values
pq.offer(1); // Add an element — O(log n)
pq.poll(); // Remove and return the head (min/max) — O(log n)
pq.peek(); // Return the head — O(1)
pq.size(); // Get the size
pq.isEmpty(); // Check if empty
pq.remove(1); // Remove specific element — O(n)
pq.contains(1); // Check if element exists — O(n)
// Custom comparator examples
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[0] - b[0]); // Sort by first element
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]); // Sort by first, then second
// Top-K pattern: use a min heap of size K
PriorityQueue<Integer> pq = new PriorityQueue<>();
for (int num : nums) {
pq.offer(num);
if (pq.size() > k) pq.poll();
}
// pq now contains the K largest elements, pq.peek() is the K-th largest
Classes
String
String str = "Hello, World!";
int len = str.length(); // Get the length
char ch = str.charAt(0); // Get char at index — O(1)
String sub = str.substring(0, 5); // Substring [0, 5) → "Hello"
String[] parts = str.split(","); // Split by delimiter
String newStr = str.replace("Hello", "Hi"); // Replace all occurrences
String lower = str.toLowerCase();
String upper = str.toUpperCase();
String trimmed = str.trim(); // Remove leading and trailing whitespace
boolean starts = str.startsWith("Hello");
boolean ends = str.endsWith("!");
int idx = str.indexOf("World"); // First index of substring, -1 if not found
int idx = str.lastIndexOf("l"); // Last index
boolean eq = str.equals("Hello"); // Compare strings (DON'T use ==)
int cmp = str.compareTo("other"); // Lexicographic comparison
char[] chars = str.toCharArray(); // Convert to char array
String s = new String(chars); // Convert char array to string
String s = String.valueOf(chars); // Convert char array to string
String s = String.valueOf(123); // Convert int to string
int n = Integer.parseInt("123"); // Convert string to int
// Join strings
String.join(",", "a", "b", "c"); // "a,b,c"
String.join(",", list); // Join a collection
// Check character type
Character.isLetter('a'); // true
Character.isDigit('1'); // true
Character.isLetterOrDigit('a'); // true
Character.isLowerCase('a'); // true
Character.isUpperCase('A'); // true
Character.toLowerCase('A'); // 'a'
Character.toUpperCase('a'); // 'A'
StringBuilder
StringBuilder sb = new StringBuilder();
StringBuilder sb = new StringBuilder("Hello");
sb.append("World"); // Append string — O(1) amortized
sb.append('!'); // Append char
sb.append(123); // Append int
sb.insert(5, " "); // Insert at index — O(n)
sb.delete(0, 5); // Delete range [0, 5) — O(n)
sb.deleteCharAt(0); // Delete char at index — O(n)
sb.replace(0, 5, "Hi"); // Replace range with string
sb.reverse(); // Reverse in place — O(n)
sb.charAt(0); // Get char at index
sb.setCharAt(0, 'h'); // Set char at index
sb.length(); // Get length
sb.toString(); // Convert to String
// Common pattern: build string efficiently
StringBuilder sb = new StringBuilder();
for (String s : list) {
if (sb.length() > 0) sb.append(",");
sb.append(s);
}
return sb.toString();
Math
Math.max(a, b); // Maximum of two values
Math.min(a, b); // Minimum of two values
Math.abs(a); // Absolute value
Math.pow(2, 10); // 2^10 = 1024.0 (returns double)
Math.sqrt(16); // 4.0
Math.log(Math.E); // 1.0 (natural log)
Math.log10(100); // 2.0
Math.ceil(2.3); // 3.0 (round up)
Math.floor(2.7); // 2.0 (round down)
Math.round(2.5); // 3 (round to nearest)
Math.random(); // Random double in [0.0, 1.0)
// Integer limits
Integer.MAX_VALUE; // 2147483647 (2^31 - 1)
Integer.MIN_VALUE; // -2147483648 (-2^31)
Long.MAX_VALUE; // 9223372036854775807
Long.MIN_VALUE; // -9223372036854775808
// Overflow-safe comparison (instead of a - b which may overflow)
Integer.compare(a, b); // Returns negative, 0, or positive
Type Conversions
// String ↔ Number
int n = Integer.parseInt("123");
long l = Long.parseLong("123");
double d = Double.parseDouble("1.23");
String s = String.valueOf(123); // or Integer.toString(123)
// char ↔ int
int digit = ch - '0'; // char '3' → int 3
char ch = (char) (digit + '0'); // int 3 → char '3'
int letterIdx = ch - 'a'; // char 'c' → int 2
char ch = (char) (idx + 'a'); // int 2 → char 'c'
// Integer ↔ int (auto-boxing)
Integer obj = 5; // auto-boxing
int val = obj; // auto-unboxing
// Array ↔ List
List<Integer> list = Arrays.stream(arr).boxed().collect(Collectors.toList()); // int[] → List<Integer>
int[] arr = list.stream().mapToInt(i -> i).toArray(); // List<Integer> → int[]
String[] arr = list.toArray(new String[0]); // List<String> → String[]
List<String> list = Arrays.asList(arr); // String[] → List<String> (fixed-size)
List<String> list = new ArrayList<>(Arrays.asList(arr)); // String[] → mutable List
// Integer to binary string
String bin = Integer.toBinaryString(10); // "1010"
int num = Integer.parseInt("1010", 2); // 10
Bit Manipulation
// Basic operations
a & b // AND
a | b // OR
a ^ b // XOR
~a // NOT (bitwise complement)
a << n // Left shift (multiply by 2^n)
a >> n // Right shift (divide by 2^n, sign-preserving)
a >>> n // Unsigned right shift
// Common tricks
n & 1 // Check if n is odd (1 if odd, 0 if even)
n & (n - 1) // Remove lowest set bit (0 if n is power of 2)
n | (n + 1) // Set lowest unset bit
n & (-n) // Isolate lowest set bit
Integer.bitCount(n) // Count number of set bits
Integer.highestOneBit(n) // Highest set bit value
Integer.numberOfLeadingZeros(n) // Leading zeros
Integer.numberOfTrailingZeros(n) // Trailing zeros
// XOR properties
a ^ a = 0 // Same values cancel out
a ^ 0 = a // XOR with 0 is identity
// Use case: find the single number in array where every other appears twice
int result = 0;
for (int num : nums) result ^= num;
// Bitmask to represent a set of elements
int mask = 0;
mask |= (1 << i); // Add element i to set
mask &= ~(1 << i); // Remove element i from set
(mask >> i) & 1 // Check if element i is in set
mask = 0 // Empty set
mask = (1 << n) - 1 // Universal set {0, 1, ..., n-1}
// Enumerate all subsets of a bitmask
for (int sub = mask; sub > 0; sub = (sub - 1) & mask) {
// process subset 'sub'
}
Common Patterns & Algorithms
Binary Search
// Standard binary search
int lo = 0, hi = arr.length - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2; // Avoid overflow
if (arr[mid] == target) return mid;
else if (arr[mid] < target) lo = mid + 1;
else hi = mid - 1;
}
return -1; // Not found
// Lower bound: first index where arr[i] >= target
int lo = 0, hi = arr.length;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (arr[mid] < target) lo = mid + 1;
else hi = mid;
}
return lo;
// Upper bound: first index where arr[i] > target
int lo = 0, hi = arr.length;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (arr[mid] <= target) lo = mid + 1;
else hi = mid;
}
return lo;
Two Pointers
// Opposite direction (e.g., two-sum in sorted array, palindrome check)
int left = 0, right = arr.length - 1;
while (left < right) {
int sum = arr[left] + arr[right];
if (sum == target) return new int[]{left, right};
else if (sum < target) left++;
else right--;
}
// Same direction / fast-slow (e.g., remove duplicates, linked list cycle)
int slow = 0;
for (int fast = 0; fast < arr.length; fast++) {
if (arr[fast] != arr[slow]) {
slow++;
arr[slow] = arr[fast];
}
}
Sliding Window
// Fixed size window
int windowSum = 0;
for (int i = 0; i < arr.length; i++) {
windowSum += arr[i];
if (i >= k) windowSum -= arr[i - k]; // Remove leftmost element
if (i >= k - 1) result = Math.max(result, windowSum); // Window is full
}
// Variable size window (e.g., minimum window substring)
int left = 0;
for (int right = 0; right < arr.length; right++) {
// Expand: add arr[right] to window
while (windowIsInvalid) {
// Shrink: remove arr[left] from window
left++;
}
// Update result
}
DFS & BFS on Grid
// 4 directions
int[][] dirs = {{0,1},{0,-1},{1,0},{-1,0}};
// 8 directions (including diagonals)
int[][] dirs = {{0,1},{0,-1},{1,0},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
// BFS on grid
Queue<int[]> queue = new LinkedList<>();
boolean[][] visited = new boolean[rows][cols];
queue.offer(new int[]{startRow, startCol});
visited[startRow][startCol] = true;
int steps = 0;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
int[] curr = queue.poll();
for (int[] dir : dirs) {
int nr = curr[0] + dir[0], nc = curr[1] + dir[1];
if (nr >= 0 && nr < rows && nc >= 0 && nc < cols
&& !visited[nr][nc] && grid[nr][nc] != obstacle) {
visited[nr][nc] = true;
queue.offer(new int[]{nr, nc});
}
}
}
steps++;
}
// DFS on grid
void dfs(int[][] grid, boolean[][] visited, int r, int c) {
if (r < 0 || r >= grid.length || c < 0 || c >= grid[0].length
|| visited[r][c] || grid[r][c] == 0) return;
visited[r][c] = true;
for (int[] dir : dirs) {
dfs(grid, visited, r + dir[0], c + dir[1]);
}
}
Union-Find (Disjoint Set)
class UnionFind {
int[] parent, rank;
int count; // Number of connected components
UnionFind(int n) {
parent = new int[n];
rank = new int[n];
count = n;
for (int i = 0; i < n; i++) parent[i] = i;
}
int find(int x) {
if (parent[x] != x) parent[x] = find(parent[x]); // Path compression
return parent[x];
}
boolean union(int x, int y) {
int px = find(x), py = find(y);
if (px == py) return false;
if (rank[px] < rank[py]) { int temp = px; px = py; py = temp; }
parent[py] = px; // Union by rank
if (rank[px] == rank[py]) rank[px]++;
count--;
return true;
}
boolean connected(int x, int y) { return find(x) == find(y); }
}
Trie (Prefix Tree)
class TrieNode {
TrieNode[] children = new TrieNode[26];
boolean isEnd = false;
}
class Trie {
TrieNode root = new TrieNode();
void insert(String word) {
TrieNode node = root;
for (char c : word.toCharArray()) {
if (node.children[c - 'a'] == null)
node.children[c - 'a'] = new TrieNode();
node = node.children[c - 'a'];
}
node.isEnd = true;
}
boolean search(String word) {
TrieNode node = searchPrefix(word);
return node != null && node.isEnd;
}
boolean startsWith(String prefix) {
return searchPrefix(prefix) != null;
}
private TrieNode searchPrefix(String word) {
TrieNode node = root;
for (char c : word.toCharArray()) {
if (node.children[c - 'a'] == null) return null;
node = node.children[c - 'a'];
}
return node;
}
}
Graph (Adjacency List)
// Build adjacency list
List<List<Integer>> graph = new ArrayList<>();
for (int i = 0; i < n; i++) graph.add(new ArrayList<>());
for (int[] edge : edges) {
graph.get(edge[0]).add(edge[1]);
graph.get(edge[1]).add(edge[0]); // Undirected graph
}
// Or using Map (when nodes are not 0-indexed integers)
Map<Integer, List<Integer>> graph = new HashMap<>();
for (int[] edge : edges) {
graph.computeIfAbsent(edge[0], k -> new ArrayList<>()).add(edge[1]);
graph.computeIfAbsent(edge[1], k -> new ArrayList<>()).add(edge[0]);
}
// Topological Sort (Kahn's Algorithm — BFS)
int[] inDegree = new int[n];
for (int[] edge : edges) inDegree[edge[1]]++;
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < n; i++) {
if (inDegree[i] == 0) queue.offer(i);
}
List<Integer> order = new ArrayList<>();
while (!queue.isEmpty()) {
int node = queue.poll();
order.add(node);
for (int neighbor : graph.get(node)) {
if (--inDegree[neighbor] == 0) queue.offer(neighbor);
}
}
// If order.size() != n, there's a cycle
Sorting Tricks
// Sort array of integers
Arrays.sort(arr); // O(n log n) — Dual-Pivot Quicksort for primitives
// Sort array of objects (stable — TimSort)
Integer[] arr = {3, 1, 2};
Arrays.sort(arr, (a, b) -> b - a); // Descending
Arrays.sort(arr, Comparator.reverseOrder());
// Sort by multiple criteria
Arrays.sort(people, (a, b) -> {
if (a[0] != b[0]) return a[0] - b[0]; // First by height
return b[1] - a[1]; // Then by weight descending
});
// Sort a list
list.sort(Comparator.naturalOrder());
list.sort(Comparator.comparingInt(a -> a[0])); // Sort by first element
list.sort(Comparator.comparing(String::length).thenComparing(Comparator.naturalOrder()));
Useful Snippets
// Swap two values (no utility method in Java)
int temp = a; a = b; b = temp;
// GCD (Greatest Common Divisor)
int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
// LCM (Least Common Multiple)
int lcm(int a, int b) { return a / gcd(a, b) * b; } // Divide first to avoid overflow
// Fast power (modular exponentiation)
long power(long base, long exp, long mod) {
long result = 1;
base %= mod;
while (exp > 0) {
if ((exp & 1) == 1) result = result * base % mod;
base = base * base % mod;
exp >>= 1;
}
return result;
}
// Prefix sum
int[] prefix = new int[n + 1];
for (int i = 0; i < n; i++) prefix[i + 1] = prefix[i] + arr[i];
// Sum of range [l, r] = prefix[r + 1] - prefix[l]
// Random
Random rand = new Random();
int r = rand.nextInt(n); // Random int in [0, n)
// Collections utility
Collections.min(list);
Collections.max(list);
Collections.frequency(list, element);