Mixed Patterns
This guide covers 18 Blind 75 problems that don't belong to a single dedicated pattern guide — they use array scanning, HashMap grouping, prefix/suffix arrays, palindromic expansion, matrix manipulation, HashSet sequential scan, and bit manipulation.
- All 18 problems here are Blind 75 — every one is interview-essential by definition
- Patterns are simpler than the main guides but these problems appear constantly as warm-ups, early-round screens, or standalone problems
- Prioritize if short on time: Max Subarray, Group Anagrams, Longest Palindromic Substring, Product Except Self
Quick Revision - Must Do Problems
Every problem in this guide is Blind 75 — all are must-do.
| # | Problem | Pattern | Why It's Essential | Time to Solve |
|---|---|---|---|---|
| 1 | Best Time to Buy and Sell Stock [B75-121] | One-Pass | Teaches track-min-so-far pattern | 5 min |
| 2 | Contains Duplicate [B75-217] | HashSet | Trivial HashSet problem — warm-up | 5 min |
| 3 | Valid Anagram [B75-242] | Frequency Count | Foundation of all anagram problems | 5 min |
| 4 | Number of 1 Bits [B75-191] | Bit Manipulation | Teaches the n & (n-1) trick | 5 min |
| 5 | Counting Bits [B75-338] | Bit DP | dp[i] = dp[i/2] + (i is odd?) | 10 min |
| 6 | Missing Number [B75-268] | XOR / Math | XOR cancellation — elegant one-liner | 5 min |
| 7 | Reverse Bits [B75-190] | Bit Shifting | Bit-by-bit extraction and placement | 10 min |
| 8 | Maximum Subarray [B75-53] | Kadane's | Most important 1D DP / greedy hybrid | 10 min |
| 9 | Group Anagrams [B75-49] | HashMap + Sort | Sorted string as key — groups all anagram families | 15 min |
| 10 | Product of Array Except Self [B75-238] | Prefix/Suffix | Two-pass O(1) space — teaches prefix thinking | 20 min |
| 11 | Maximum Product Subarray [B75-152] | Kadane's Variant | Track both max and min — negatives can flip | 20 min |
| 12 | Longest Palindromic Substring [B75-5] | Expand Around Center | Odd + even center expansion | 20 min |
| 13 | Palindromic Substrings [B75-647] | Expand Around Center | Same expansion, count all palindromes found | 15 min |
| 14 | Set Matrix Zeroes [B75-73] | Matrix In-Place | First row/col as flags — O(1) space trick | 20 min |
| 15 | Spiral Matrix [B75-54] | Matrix Boundary | Four boundary pointers shrinking inward | 20 min |
| 16 | Rotate Image [B75-48] | Matrix In-Place | Transpose + reverse rows = 90° rotation | 15 min |
| 17 | Sum of Two Integers [B75-371] | Bit Manipulation | XOR = sum bits, AND<<1 = carry bits | 15 min |
| 18 | Longest Consecutive Sequence [B75-128] | HashSet / Sequential Scan | O(n) via start-of-sequence detection — tests set-based thinking | 15 min |
Practice Tips
How to Identify Each Pattern
- Kadane's: "max/min subarray sum/product" — running state that either extends or restarts
- HashMap / HashSet: "find pair with sum", "detect duplicate", "count frequencies" — O(1) lookup replaces O(n) scan
- Prefix/Suffix: "product/sum of everything except self" — two passes, each direction builds one half
- Palindrome Expand: "longest/count palindromic substrings" — try every center (2n-1 centers)
- Matrix: "set to zero", "spiral order", "rotate in-place" — boundary pointers or flag arrays
- Bit Manipulation: "without arithmetic operators", "count set bits", "XOR to find unique" — bit tricks
Interview Approach
- For array problems: ask yourself if a running variable (min so far, max so far, current sum) solves it before reaching for sorting or extra space
- For matrix in-place problems: identify if you can reuse the first row/column as storage, or if transpose + reverse achieves the rotation
- For bit problems: know the three core tricks —
n & (n-1)clears lowest bit, XOR cancels pairs, AND + left shift simulates carry
6 Main Patterns
Pattern 1: One-Pass Array (Kadane's Family)
// Track a running state that resets when continuing would be worse than starting fresh
int curr = nums[0], best = nums[0];
for (int i = 1; i < nums.length; i++) {
curr = Math.max(nums[i], curr + nums[i]); // extend or restart
best = Math.max(best, curr);
}
Pattern 2: HashMap / HashSet Lookup
// O(1) lookup replaces O(n) search — store what you've seen as you go
Map<Integer, Integer> map = new HashMap<>(); // value → index
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) {
return new int[]{map.get(complement), i};
}
map.put(nums[i], i);
}
Pattern 3: Prefix / Suffix Pass
// Pass 1: build prefix into result[]; Pass 2: apply suffix in one variable
int[] result = new int[n];
result[0] = 1;
for (int i = 1; i < n; i++) {
result[i] = result[i-1] * nums[i-1]; // prefix
}
int suffix = 1;
for (int i = n-1; i >= 0; i--) { result[i] *= suffix; suffix *= nums[i]; } // suffix
Pattern 4: Palindrome Expand Around Center
// 2n-1 possible centers: each character (odd) and each gap (even)
private int expand(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
left--; right++;
}
return right - left - 1; // palindrome length
}
// Call: expand(s, i, i) for odd, expand(s, i, i+1) for even
Pattern 5: Matrix In-Place
// Rotate 90° clockwise = transpose + reverse each row
// Transpose: swap matrix[i][j] with matrix[j][i] for j > i
// Reverse rows: standard two-pointer swap within each row
Pattern 6: Bit Manipulation
n & (n - 1) // clear lowest set bit (count set bits, check power of 2)
a ^ b // XOR: same bits cancel, different bits survive
a & b // AND: 1 only where both are 1 (carry in bit addition)
(a & b) << 1 // carry bits in bit addition
n >> 1 // right shift = divide by 2 (used in Counting Bits: dp[n>>1])
General Templates
Bit Addition Template (Sum of Two Integers)
while (b != 0) {
int carry = (a & b) << 1;
a = a ^ b; // sum without carry
b = carry; // carry becomes next b
}
return a;
Problems in this guide
Problem 1: Best Time to Buy and Sell Stock ⭐ MUST DO [B75-121]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Easy | 5 min | One-Pass (Track Min) |
Choose a day to buy and a later day to sell. Return the maximum profit. Return 0 if no profit is possible.
Example:
Input: [7,1,5,3,6,4] → 5 (buy at 1, sell at 6)
Input: [7,6,4,3,1] → 0 (prices only fall)
Solution:
public int maxProfit(int[] prices) {
int minPrice = Integer.MAX_VALUE, maxProfit = 0;
for (int price : prices) {
minPrice = Math.min(minPrice, price);
maxProfit = Math.max(maxProfit, price - minPrice);
}
return maxProfit;
}
Complexity:
| Time | O(n) |
| Space | O(1) |
LC 122 — Unlimited transactions: Greedy: capture every upward step. Sell-before-buy is implicit — consecutive up-days (2-1)+(3-2) equal one holding (3-1), and you never hold through a down day.
public int maxProfitII(int[] prices) {
int profit = 0;
for (int i = 1; i < prices.length; i++) {
if (prices[i] > prices[i-1]) {
profit += prices[i] - prices[i-1]; // take every upward step
}
}
return profit;
}
LC 714 — Unlimited with transaction fee: Same greedy but subtract fee on each sell. Two states: held (holding), cash (not holding).
public int maxProfitFee(int[] prices, int fee) {
int held = -prices[0]; // profit while holding (paid to buy)
int cash = 0; // profit while not holding
for (int i = 1; i < prices.length; i++) {
held = Math.max(held, cash - prices[i]); // keep holding or buy
cash = Math.max(cash, held + prices[i] - fee); // keep not holding or sell
}
return cash;
}
LC 309 — Unlimited with cooldown (must skip 1 day after selling): Three states: held (holding), sold (just sold — cooldown next), rest (not holding, free to buy).
public int maxProfitCooldown(int[] prices) {
int held = Integer.MIN_VALUE; // profit while holding a stock
int sold = 0; // profit on day we just sold (next day is forced rest)
int rest = 0; // profit while resting (can buy next day)
for (int price : prices) {
int prevHeld = held;
int prevSold = sold;
int prevRest = rest;
held = Math.max(prevHeld, prevRest - price); // keep holding, or buy (only from rest)
sold = prevHeld + price; // sell what we held
rest = Math.max(prevRest, prevSold); // keep resting, or cooldown just elapsed
}
return Math.max(sold, rest);
}
LC 123 — At most 2 transactions: Four states cascade in one pass: buy1 → sell1 → buy2 → sell2. Each state funds the next.
public int maxProfitTwo(int[] prices) {
int buy1 = Integer.MIN_VALUE, sell1 = 0;
int buy2 = Integer.MIN_VALUE, sell2 = 0;
for (int price : prices) {
buy1 = Math.max(buy1, -price); // best profit after 1st buy
sell1 = Math.max(sell1, buy1 + price); // best profit after 1st sell
buy2 = Math.max(buy2, sell1 - price); // 2nd buy funded by sell1
sell2 = Math.max(sell2, buy2 + price); // best profit after 2nd sell
}
return sell2;
}
LC 188 — At most k transactions: Generalises LC 123 to k buy/sell pairs. Short-circuits to greedy when k >= n/2 (more allowed trades than profitable days).
public int maxProfitK(int k, int[] prices) {
int n = prices.length;
if (k >= n / 2) {
// effectively unlimited — use greedy
int profit = 0;
for (int i = 1; i < n; i++) {
if (prices[i] > prices[i-1]) {
profit += prices[i] - prices[i-1];
}
}
return profit;
}
int[] buy = new int[k + 1];
int[] sell = new int[k + 1];
Arrays.fill(buy, Integer.MIN_VALUE);
for (int price : prices) {
for (int j = 1; j <= k; j++) {
buy[j] = Math.max(buy[j], sell[j-1] - price); // buy on j-th transaction
sell[j] = Math.max(sell[j], buy[j] + price); // sell on j-th transaction
}
}
return sell[k];
}
How the variants relate:
| LC | Constraint | Approach |
|---|---|---|
| 121 | 1 transaction | Track running min |
| 122 | Unlimited | Greedy — every up-step |
| 714 | Unlimited + fee | LC 122 minus fee on sell |
| 309 | Unlimited + cooldown | 3-state DP (held / sold / rest) |
| 123 | ≤ 2 transactions | 4 cascading states |
| 188 | ≤ k transactions | LC 123 generalised; degenerates to LC 122 when k is large |
Real World: Algorithmic trading systems compute the maximum profit window over historical price data before deploying a strategy. The same one-pass pattern applies to any "cheapest buy, best sell" optimisation: cloud spot-instance pricing (buy compute cheapest, release at peak), commodity procurement, or ad-bid optimisation.
Variations:
- Maximum profit with cooldown (LC 309) — after selling you must wait one day; DP with three states: hold, sold, rest.
- Maximum profit with transaction fee (LC 714) — pay a fixed fee per sell; same greedy but subtract fee each time you capture an upward step.
Interview Disguises:
- "Given hourly cloud spot-instance prices, find the cheapest time to start a batch job and the best time to stop it to minimise total cost." — max profit; cost replaces price, minimise replaces maximise.
- "Given an array of sensor readings, find the maximum increase from any earlier reading to any later reading." — same structure; the answer is the maximum difference where the larger comes after the smaller.
Problem 2: Contains Duplicate ⭐ MUST DO [B75-217]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Easy | 5 min | HashSet |
Return true if any value appears at least twice in the array.
Example:
Input: [1,2,3,1] → true
Input: [1,2,3,4] → false
Solution:
public boolean containsDuplicate(int[] nums) {
Set<Integer> seen = new HashSet<>();
for (int num : nums) {
if (!seen.add(num)) {
return true; // add() returns false if already present
}
}
return false;
}
Complexity:
| Time | O(n) |
| Space | O(n) |
Real World: Data deduplication pipelines check for repeated records before inserting into a database. Fraud detection systems flag the same transaction ID appearing more than once. Log aggregators deduplicate identical error messages within a time window before alerting.
Variations:
- Contains duplicate within k distance (LC 219) — use a sliding HashSet of size k; add new element, remove element that fell out of window.
- Contains duplicate within value range t (LC 220) — use a TreeSet to find the nearest element in O(log k) and check if the value difference is within t.
Interview Disguises:
- "A payment processor receives transaction IDs; flag any ID that has been submitted more than once in the same batch." — contains duplicate; transaction IDs are the values.
- "Verify that a list of generated UUIDs has no collisions." — same HashSet check; false means all unique, true means collision detected.
Problem 3: Valid Anagram ⭐ MUST DO [B75-242]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Easy | 5 min | Frequency Count |
Return true if t is an anagram of s (same characters, same counts).
Example:
Input: s = "anagram", t = "nagaram" → true
Input: s = "rat", t = "car" → false
Solution:
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) {
return false;
}
int[] count = new int[26];
for (int i = 0; i < s.length(); i++) {
count[s.charAt(i) - 'a']++;
count[t.charAt(i) - 'a']--;
}
for (int c : count) {
if (c != 0) return false;
}
return true;
}
Complexity:
| Time | O(n) |
| Space | O(1) — fixed 26-element array |
Real World: Search engines normalise query terms before indexing — "listen" and "silent" map to the same canonical form. Spell checkers and autocomplete systems detect that a mistyped word is an anagram of a real word. Plagiarism detectors flag sentences whose words are rearranged.
Variations:
- Unicode strings — replace
int[26]with aHashMap<Character, Integer>; handles any character set. - Anagram of any substring (LC 438) — sliding window with a frequency array; find all start indices where a window of length
p.length()is an anagram of p.
Interview Disguises:
- "Two configuration files list the same set of feature flags in different order — verify they are identical." — valid anagram where feature flag names are characters.
- "A shuffled deck of cards is claimed to be a full standard deck — verify without sorting." — frequency count both sequences and compare.
Problem 4: Number of 1 Bits ⭐ MUST DO [B75-191]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Easy | 5 min | Bit Manipulation |
Return the number of set bits (1s) in the binary representation of n.
Example:
Input: n = 11 (binary: 1011) → 3
Input: n = 128 (binary: 10000000) → 1
Key Insight:
n & (n-1)clears the lowest set bit. Count how many times you can do this before n becomes 0.
Solution:
public int hammingWeight(int n) {
int count = 0;
while (n != 0) {
n &= (n - 1); // clear lowest set bit
count++;
}
return count;
}
Complexity:
| Time | O(number of set bits) ≤ O(32) |
| Space | O(1) |
Real World:
Network packet headers encode feature flags as bitmasks — counting set bits tells you how many features are active. CPU instruction sets include a dedicated POPCNT instruction for this; software implementations use n &= (n-1) for the same reason. Compression algorithms use bit counts to compute Hamming distances between codewords.
Variations:
- Hamming distance (LC 461) — XOR the two numbers then count set bits; XOR isolates the bits that differ.
- Power of two check —
n > 0 && (n & (n-1)) == 0; a power of two has exactly one set bit so clearing it yields zero.
Interview Disguises:
- "Given a permission bitmask, return how many individual permissions are granted." — count set bits; each bit is a permission flag.
- "Two users have feature-flag bitmasks — how many features does each have enabled?" — popcount on each mask.
Problem 5: Counting Bits ⭐ MUST DO [B75-338]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Easy | 10 min | Bit DP |
Return an array where result[i] is the number of 1 bits in i, for all i from 0 to n.
Example:
Input: n = 5 → [0,1,1,2,1,2]
Key Insight:
dp[i] = dp[i >> 1] + (i & 1). Shifting right divides by 2 (drops the last bit);i & 1adds 1 if that dropped bit was a 1. So every number's bit count is its half's count plus whether it's odd.
Solution:
public int[] countBits(int n) {
int[] dp = new int[n + 1];
for (int i = 1; i <= n; i++) {
dp[i] = dp[i >> 1] + (i & 1); // dp[i/2] + is_i_odd
}
return dp;
}
Complexity:
| Time | O(n) |
| Space | O(n) — output array |
Real World: Pre-computing a popcount lookup table is a standard optimisation in database engines and hash functions — build it once using this DP, then use O(1) lookups. Compiler backends use bit-count tables when generating SIMD instructions for population count.
Variations:
- Sum of all bits from 0 to n — sum the output array; useful for computing total bit complexity across a range.
- Numbers with exactly k set bits — filter the output array or generate them directly using bitmask enumeration.
Interview Disguises:
- "Pre-compute a table of how many 1-bits each byte value (0–255) contains, to be used as a lookup in a network packet parser." — counting bits for n=255; the DP approach fills the table in O(n).
- "For each integer from 0 to n, compute the number of on-pixels if that integer were displayed on a binary display grid." — identical; on-pixels = set bits.
Problem 6: Missing Number ⭐ MUST DO [B75-268]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Easy | 5 min | XOR |
Given an array containing n distinct numbers in range [0, n], return the one missing number.
Example:
Input: [3,0,1] → 2
Input: [9,6,4,2,3,5,7,0,1] → 8
Key Insight:
- XOR every index (0 to n) and every value in the array. Each number that's present cancels itself (a ^ a = 0). The unpaired index — the missing number — survives.
Solution:
public int missingNumber(int[] nums) {
int xor = nums.length; // start with n
for (int i = 0; i < nums.length; i++) {
xor ^= i ^ nums[i]; // cancel each present pair
}
return xor;
}
Complexity:
| Time | O(n) |
| Space | O(1) |
Real World: Detecting gaps in sequential IDs is a common data quality check — order numbers, invoice IDs, and event sequence numbers should be contiguous. A missing ID means a record was dropped or skipped. The same XOR trick is used in distributed systems to verify that a replica received exactly the expected set of messages.
Variations:
- Find the duplicate instead of missing — if one number is duplicated instead of missing, the same XOR of indices and values isolates it because the duplicate cancels twice while the missing one cancels once.
- First missing positive (LC 41) — harder variant; values are not bounded by n, so XOR doesn't apply; use index-as-hash instead.
Interview Disguises:
- "A conveyor belt assigns sequential ticket numbers 1 to n. One ticket was lost — which number is missing from the scanned list?" — missing number; ticket numbers are the values.
- "Verify that a distributed job queue processed every task ID from 0 to n exactly once; report the missing task." — same XOR approach.
Problem 7: Reverse Bits ⭐ MUST DO [B75-190]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Easy | 10 min | Bit Shifting |
Reverse the bits of a 32-bit unsigned integer.
Example:
Input: 00000010100101000001111010011100 → 00111001011110000010100101000000
(43261596) (964176192)
Solution:
public int reverseBits(int n) {
int result = 0;
for (int i = 0; i < 32; i++) {
result = (result << 1) | (n & 1); // shift result left, append LSB of n
n >>>= 1; // unsigned right shift to expose next bit
}
return result;
}
Complexity:
| Time | O(32) = O(1) |
| Space | O(1) |
Real World: Network protocols transmit data in big-endian (most significant byte first) or little-endian order. Reversing bits corrects byte-order mismatches between hardware architectures. CRC checksum calculations and cryptographic hash functions use bit reversal as a building block.
Variations:
- Reverse only k bits — mask off the top (32-k) bits, reverse the bottom k, then OR them back.
- Palindrome in binary — reverse the bits and compare to the original; equal means palindrome.
Interview Disguises:
- "A legacy sensor encodes its reading with the least significant bit first. Convert it to standard big-endian format." — reverse bits; the sensor output is the input integer.
- "A hardware protocol sends 32-bit addresses in mirrored bit order — decode an incoming address." — same reversal; address bits are the input.
Problem 8: Maximum Subarray ⭐ MUST DO [B75-53]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Medium | 10-15 min | Kadane's |
Find the contiguous subarray with the largest sum.
Example:
Input: [-2,1,-3,4,-1,2,1,-5,4] → 6 ([4,-1,2,1])
Input: [1] → 1
Key Insight:
- At each element, decide: start a new subarray here, or extend the running subarray? If the running sum is negative, starting fresh is better. Update the global max at each step. This is Kadane's algorithm.
Solution:
public int maxSubArray(int[] nums) {
int curr = nums[0], max = nums[0];
for (int i = 1; i < nums.length; i++) {
curr = Math.max(nums[i], curr + nums[i]); // restart or extend
max = Math.max(max, curr);
}
return max;
}
Complexity:
| Time | O(n) |
| Space | O(1) |
Real World: Financial time-series analysis — find the best contiguous trading period by profit, revenue, or return. Signal processing — find the peak signal window within a noisy stream. A/B test analysis — find the contiguous cohort window with the highest conversion lift.
Variations:
- Maximum circular subarray (LC 918) — total sum minus the minimum subarray gives the circular maximum; handle all-negative edge case separately.
- Return the actual subarray — track start index when
currresets and update answer indices when a new max is found.
Interview Disguises:
- "Given daily net revenue changes, find the contiguous period with the highest total net revenue." — maximum subarray; daily changes are the array values.
- "A/B test logs show daily conversion deltas. Find the window of consecutive days with the highest cumulative lift." — Kadane's; deltas are the values.
Problem 9: Group Anagrams ⭐ MUST DO [B75-49]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Medium | 15 min | HashMap + Sort |
Group strings that are anagrams of each other.
Example:
Input: ["eat","tea","tan","ate","nat","bat"]
Output: [["bat"],["nat","tan"],["ate","eat","tea"]]
Key Insight:
- Two strings are anagrams if and only if their sorted characters are identical. Use the sorted string as the HashMap key. All anagrams in the input map to the same key and get grouped together.
Solution:
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
for (String s : strs) {
char[] chars = s.toCharArray();
Arrays.sort(chars);
String key = new String(chars);
if (!map.containsKey(key)) {
map.put(key, new ArrayList<>());
}
map.get(key).add(s);
}
return new ArrayList<>(map.values());
}
Complexity:
| Time | O(n × k log k) where k is max string length |
| Space | O(n × k) — map storage |
Real World: Search engines group query variants so "listen", "silent", and "enlist" all return the same results. Log aggregation systems cluster error messages that use the same words in a different order. Spam filters flag messages whose word bags match a known spam template.
Variations:
- Frequency count key (O(nk) instead of O(nk log k)) — use a
int[26]frequency array converted to a string as the key; avoids sorting each word. - Count groups of size exactly k — filter
map.values()after building the group map.
Interview Disguises:
- "Cluster API endpoint paths that are permutations of each other so they can share a rate-limit bucket." — group anagrams where paths are the strings.
- "A chat moderation system needs to group messages that contain the same words in any order." — anagram grouping on word-sorted message tokens.
Problem 10: Product of Array Except Self ⭐ MUST DO [B75-238]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Medium | 20 min | Prefix / Suffix |
Return an array where result[i] is the product of all elements except nums[i]. Must run in O(n) without division.
Example:
Input: [1,2,3,4] → [24,12,8,6]
Input: [-1,1,0,-3,3] → [0,0,9,0,0]
Key Insight:
result[i] = (product of all elements left of i) × (product of all elements right of i). First pass fills result[] with prefix products left-to-right. Second pass multiplies in suffix products right-to-left using a single running variable — no extra array needed.
Solution:
public int[] productExceptSelf(int[] nums) {
int n = nums.length;
int[] result = new int[n];
result[0] = 1;
for (int i = 1; i < n; i++) {
result[i] = result[i-1] * nums[i-1]; // prefix product
}
int suffix = 1;
for (int i = n-1; i >= 0; i--) {
result[i] *= suffix; // apply suffix
suffix *= nums[i]; // grow suffix
}
return result;
}
Complexity:
| Time | O(n) |
| Space | O(1) — output array not counted |
Real World: Computing leave-one-out scores: each data point's score is the product (or sum) of all other points — used in cross-validation, anomaly detection, and influence analysis. Division is avoided because one zero would corrupt the entire result; the prefix/suffix approach handles zeros naturally.
Variations:
- With division (handle zeros separately) — compute total product; divide for non-zero elements; for zeros, count zeros and handle specially. Simpler but fragile.
- Sum version (trivial) — prefix sum array;
result[i] = totalSum - nums[i]. The product version is harder and more commonly asked.
Interview Disguises:
- "Each team member's performance score should reflect the combined output of all other members — compute these scores without using division." — product except self; team members are array elements.
- "Given sensor calibration weights, compute each sensor's normalisation factor as the product of all other weights." — same structure; weights are the array values.
Problem 11: Maximum Product Subarray ⭐ MUST DO [B75-152]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Medium | 20 min | Kadane's Variant |
Find the contiguous subarray with the largest product.
Example:
Input: [2,3,-2,4] → 6 ([2,3])
Input: [-2,0,-1] → 0
Key Insight:
- Unlike max subarray sum, a large negative product can become the best if multiplied by another negative. Track both the current maximum and minimum product. At each element, new max = max(nums[i], prev_max × nums[i], prev_min × nums[i]) — and similarly for min.
Solution:
public int maxProduct(int[] nums) {
int max = nums[0], min = nums[0], result = nums[0];
for (int i = 1; i < nums.length; i++) {
int tmp = max;
max = Math.max(nums[i], Math.max(max * nums[i], min * nums[i]));
min = Math.min(nums[i], Math.min(tmp * nums[i], min * nums[i]));
result = Math.max(result, max);
}
return result;
}
Complexity:
| Time | O(n) |
| Space | O(1) |
Real World: Signal gain optimisation where amplifier stages can invert the signal — a negative multiplier flips the sign but a pair of negatives restores it. Financial risk: a sequence of loss ratios (values < 1) multiplied together compounds, but a second negative period can produce an unexpected gain. Finding the maximum product window identifies the best compound-growth period.
Variations:
- Maximum product of exactly k elements — sliding window of fixed size k; maintain running product, divide out the leaving element (handle zeros separately).
- Maximum product after removing one element — try removing each element; the answer is
max(product of left prefix × product of right suffix)for each index.
Interview Disguises:
- "A manufacturing pipeline has stages with efficiency multipliers; some stages degrade quality (multiplier < 1). Find the contiguous run of stages with the highest combined multiplier." — max product subarray; efficiency multipliers are the values.
- "Given a sequence of investment return ratios (e.g. 0.9 for -10%, 1.2 for +20%), find the best consecutive holding period by total return." — max product; ratios are the values.
Problem 12: Longest Palindromic Substring ⭐ MUST DO [B75-5]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Medium | 20 min | Expand Around Center |
Return the longest palindromic substring.
Example:
Input: "babad" → "bab" (or "aba")
Input: "cbbd" → "bb"
Key Insight:
- Every palindrome has a center. Try all 2n-1 possible centers (n single characters for odd-length, n-1 gaps between characters for even-length). Expand outward while characters match. Track the longest found.
Solution:
public String longestPalindrome(String s) {
int start = 0, maxLen = 1;
for (int i = 0; i < s.length(); i++) {
int len = Math.max(expand(s, i, i), expand(s, i, i + 1));
if (len > maxLen) {
maxLen = len;
start = i - (len - 1) / 2;
}
}
return s.substring(start, start + maxLen);
}
private int expand(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
left--; right++;
}
return right - left - 1;
}
Complexity:
| Time | O(n²) — 2n-1 centers, each expand O(n) worst case |
| Space | O(1) |
Real World: DNA sequence analysis — palindromic sequences are recognition sites for restriction enzymes (the sequence reads the same on both strands in 5'→3' direction). Finding the longest palindromic region helps locate cut sites. String compression algorithms also look for palindromic substrings as redundancy candidates.
Variations:
- Manacher's algorithm O(n) — uses previously computed palindrome radii to skip redundant expansions; rarely asked to implement from scratch but worth knowing exists.
- Longest palindromic subsequence (LC 516) — characters don't need to be contiguous; DP solution, different from this problem.
Interview Disguises:
- "Find the longest mirrored segment in a user-entered password — it may indicate a weak pattern." — longest palindromic substring; the password is the input string.
- "A genomics tool needs to locate the longest restriction enzyme recognition site in a DNA strand." — same expansion logic; the strand is the string.
Problem 13: Palindromic Substrings ⭐ MUST DO [B75-647]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Medium | 15 min | Expand Around Center |
Count the number of palindromic substrings in s.
Example:
Input: "abc" → 3 ("a","b","c")
Input: "aaa" → 6 ("a","a","a","aa","aa","aaa")
Key Insight:
- Same expand-around-center as Longest Palindromic Substring, but instead of tracking the longest, count every palindrome found during each expansion (each successful expansion step = one palindrome).
Solution:
public int countSubstrings(String s) {
int count = 0;
for (int i = 0; i < s.length(); i++) {
count += expand(s, i, i); // odd-length palindromes
count += expand(s, i, i + 1); // even-length palindromes
}
return count;
}
private int expand(String s, int left, int right) {
int count = 0;
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
left--; right++; count++;
}
return count;
}
Complexity:
| Time | O(n²) |
| Space | O(1) |
Real World: Same DNA palindrome analysis — counting all restriction sites rather than just the longest. Quality control in transmitted strings: count all substrings that read the same in both directions to identify redundancy or error patterns.
Variations:
- Count palindromes of length ≥ k — same expansion, skip counting if
right - left - 1 < k. - Minimum cuts for palindrome partitioning (LC 132) — harder DP follow-up; uses the same expansion table as a subroutine.
Interview Disguises:
- "Count how many substrings of a barcode scan identically forwards and backwards — a high count may indicate a corrupted scan." — palindromic substrings count.
- "In a protein sequence, count all segments that are their own reverse complement — these are potential hairpin structures." — same expansion logic on a biological string.
Problem 14: Set Matrix Zeroes ⭐ MUST DO [B75-73]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Medium | 20 min | Matrix In-Place Flags |
If an element is 0, set its entire row and column to 0. Do it in-place.
Example:
Input: [[1,1,1],[1,0,1],[1,1,1]] → [[1,0,1],[0,0,0],[1,0,1]]
Key Insight:
- Use the first row and first column as flag arrays — if
matrix[i][j] == 0, markmatrix[i][0] = 0andmatrix[0][j] = 0. But since the first row and column are themselves used as flags, record separately whether they need to be zeroed before using them as markers.
Solution:
public void setZeroes(int[][] matrix) {
int m = matrix.length, n = matrix[0].length;
boolean firstRowZero = false, firstColZero = false;
for (int j = 0; j < n; j++) {
if (matrix[0][j] == 0) firstRowZero = true;
}
for (int i = 0; i < m; i++) {
if (matrix[i][0] == 0) firstColZero = true;
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (matrix[i][j] == 0) {
matrix[i][0] = 0; // mark row
matrix[0][j] = 0; // mark col
}
}
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (matrix[i][0] == 0 || matrix[0][j] == 0) {
matrix[i][j] = 0;
}
}
}
if (firstRowZero) {
Arrays.fill(matrix[0], 0);
}
if (firstColZero) {
for (int i = 0; i < m; i++) matrix[i][0] = 0;
}
}
Complexity:
| Time | O(m × n) |
| Space | O(1) |
Real World: Spreadsheet software propagates "null" or "unknown" values — if any cell in a row or column is unknown, the whole row and column should be marked unknown. Database NULL propagation rules follow the same logic: a NULL in any operand of a multiplication zeroes the result row and column in a cross-product.
Variations:
- Mark with -1 instead of 0 — same algorithm; just replace the zero sentinel with -1 and use a different flag value.
- Sparse matrix — if very few cells are zero, store the zero positions in a small list instead of using the first row/col as flags; avoids the tricky first-row/col bookkeeping.
Interview Disguises:
- "A table of sensor readings: if any sensor reports an invalid reading (0), mark all readings in its row and column as invalid." — set matrix zeroes; invalid readings are the zeros.
- "In a user-permission matrix, if any cell indicates a blocked permission, propagate the block to all permissions in that row and column." — same in-place flag propagation.
Problem 15: Spiral Matrix ⭐ MUST DO [B75-54]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Medium | 20 min | Matrix Boundary Shrink |
Return all elements of the matrix in spiral order.
Example:
Input: [[1,2,3],[4,5,6],[7,8,9]] → [1,2,3,6,9,8,7,4,5]
Key Insight:
- Maintain four boundaries (top, bottom, left, right). Each iteration: traverse top row left→right, advance top; right column top→bottom, advance right; bottom row right→left (if top ≤ bottom), advance bottom; left column bottom→top (if left ≤ right), advance left. Check bounds before each inner direction to handle non-square matrices.
Solution:
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> result = new ArrayList<>();
int top = 0, bottom = matrix.length - 1;
int left = 0, right = matrix[0].length - 1;
while (top <= bottom && left <= right) {
for (int j = left; j <= right; j++) {
result.add(matrix[top][j]);
}
top++;
for (int i = top; i <= bottom; i++) {
result.add(matrix[i][right]);
}
right--;
if (top <= bottom) {
for (int j = right; j >= left; j--) {
result.add(matrix[bottom][j]);
}
bottom--;
}
if (left <= right) {
for (int i = bottom; i >= top; i--) {
result.add(matrix[i][left]);
}
left++;
}
}
return result;
}
Complexity:
| Time | O(m × n) — every element visited once |
| Space | O(1) — output list not counted |
Real World: Image processing reads pixels in spiral order for certain compression codecs (e.g. JPEG block scanning). Cache-oblivious matrix algorithms access memory in spiral patterns to improve locality. Robotic path planning visits a bounded grid from the outside in to ensure full coverage.
Variations:
- Spiral Matrix II — fill instead of read (LC 59) — same boundary-shrink logic but write values 1..n² into the matrix instead of reading them out.
- Diagonal traversal (LC 498) — alternating diagonal directions; different traversal pattern but same boundary-tracking idea.
Interview Disguises:
- "A robot must clean a rectangular room by vacuuming the perimeter first, then spiralling inward. Return the order of cells visited." — spiral matrix; cells are matrix elements.
- "Print the layers of a 2D grid representing a building floor plan from outermost to innermost." — spiral order traversal.
Problem 16: Rotate Image ⭐ MUST DO [B75-48]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Medium | 15 min | Matrix In-Place |
Rotate an n×n matrix 90° clockwise in-place.
Example:
Input: [[1,2,3],[4,5,6],[7,8,9]] → [[7,4,1],[8,5,2],[9,6,3]]
Key Insight:
- Rotating 90° clockwise = transpose (flip along the main diagonal) + reverse each row. Transpose swaps
matrix[i][j]withmatrix[j][i]forj > ionly (to avoid double-swapping). Both operations are done in-place with no extra space.
Solution:
public void rotate(int[][] matrix) {
int n = matrix.length;
// Transpose
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
int tmp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = tmp;
}
}
// Reverse each row
for (int i = 0; i < n; i++) {
int l = 0, r = n - 1;
while (l < r) {
int tmp = matrix[i][l];
matrix[i][l] = matrix[i][r];
l++;
matrix[i][r] = tmp;
r--;
}
}
}
Complexity:
| Time | O(n²) |
| Space | O(1) |
Real World: Game engines rotate sprite tiles and map grids 90° when the player changes orientation — done in-place to avoid allocating a new frame buffer. Image processing pipelines (EXIF orientation correction) apply the same transpose-then-reverse sequence on pixel arrays.
Variations:
- 90° counter-clockwise — transpose then reverse each column (or reverse each row then transpose).
- 180° rotation — reverse the entire matrix row-by-row then reverse each row, or apply two 90° clockwise rotations.
Interview Disguises:
- "A map tile engine needs to rotate a terrain grid 90° clockwise when the user rotates the device — do it without allocating a new grid." — rotate image; terrain values are matrix elements.
- "Rotate a Sudoku board 90° clockwise as part of a puzzle generation step." — same in-place rotation; Sudoku grid is the matrix.
Problem 17: Sum of Two Integers ⭐ MUST DO [B75-371]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Medium | 15 min | Bit Manipulation |
Calculate the sum of two integers without using + or -.
Example:
Input: a = 1, b = 2 → 3
Input: a = 2, b = 3 → 5
Key Insight:
- XOR of two numbers gives the sum bits without any carry. AND of two numbers shifted left by 1 gives the carry bits. Repeat — add the carry into the sum — until no carry remains.
Solution:
public int getSum(int a, int b) {
while (b != 0) {
int carry = (a & b) << 1; // carry bits
a = a ^ b; // sum without carry
b = carry;
}
return a;
}
Complexity:
| Time | O(1) — at most 32 iterations |
| Space | O(1) |
Real World:
Low-level arithmetic in embedded systems and hardware description languages where the + operator may not be available or is implemented in terms of bitwise gates. ALU design: a full adder is constructed from XOR (sum) and AND (carry) gates, exactly this algorithm repeated at each bit position.
Variations:
- Subtract without
-— negate b using two's complement (~b + 1using the same add-without-plus), then add. - Multiply without
*— repeated addition using bit shifts; shiftaleft and add when the corresponding bit ofbis set.
Interview Disguises:
- "Implement addition for a processor that has only bitwise AND, OR, XOR, and shift instructions." — sum of two integers; the constraint is the whole point.
- "Design a 4-bit software ALU that supports addition without using Java's + operator." — same carry-propagation logic applied to 4 bits.
Problem 18: Longest Consecutive Sequence ⭐ MUST DO [B75-128]
| Difficulty | Time to Solve | Pattern |
|---|---|---|
| Medium | 15-20 min | HashSet / Sequential Scan |
Given an unsorted array, return the length of the longest consecutive elements sequence. Must run in O(n).
Example:
Input: [100, 4, 200, 1, 3, 2]
Output: 4 (sequence 1, 2, 3, 4)
Input: [0, 3, 7, 2, 5, 8, 4, 6, 0, 1]
Output: 9
Key Insight:
- Add all numbers to a HashSet for O(1) lookup. A number is the start of a sequence only if
n - 1is not in the set. From each start, count consecutive numbers by checkingn + 1,n + 2, ... — each number is visited at most twice total across all sequences.
Solution:
public int longestConsecutive(int[] nums) {
Set<Integer> set = new HashSet<>();
for (int n : nums) {
set.add(n);
}
int longest = 0;
for (int n : set) {
if (!set.contains(n - 1)) { // only start from sequence beginnings
int length = 1;
while (set.contains(n + length)) {
length++;
}
longest = Math.max(longest, length);
}
}
return longest;
}
Complexity:
| Time | O(n) — each number checked at most twice |
| Space | O(n) — HashSet |
Real World: Detecting gaps in sequential event logs — order numbers, invoice IDs, and packet sequence numbers should be contiguous. A long consecutive run in user IDs may indicate a bot sweep registering accounts in bulk. Network diagnostics use the same pattern to find the longest uninterrupted packet sequence in a capture.
Variations:
- Return the actual sequence — track the starting number and length when a new maximum is found; reconstruct by iterating from start to start+length.
- Longest consecutive path in a binary tree (LC 298) — DFS variant; consecutive means parent value + 1 equals child value.
Interview Disguises:
- "Given a list of user IDs that signed up today, find the longest run of consecutive IDs — a long run may indicate automated registration." — longest consecutive sequence; IDs are the values.
- "Given packet sequence numbers received so far, find the longest contiguous run with no gaps to determine the reliable delivery window." — same HashSet start-detection logic.
Quick Reference Table
| # | Problem | Pattern | Key Technique | Time |
|---|---|---|---|---|
| 1 | Best Time Stock ⭐ [B75-121] | One-Pass | Track min price so far | O(n) |
| 2 | Contains Duplicate ⭐ [B75-217] | HashSet | set.add() returns false on duplicate | O(n) |
| 3 | Valid Anagram ⭐ [B75-242] | Frequency | count[26], increment s, decrement t | O(n) |
| 4 | Number of 1 Bits ⭐ [B75-191] | Bit | n &= (n-1) clears lowest set bit | O(1) |
| 5 | Counting Bits ⭐ [B75-338] | Bit DP | dp[i] = dp[i>>1] + (i&1) | O(n) |
| 6 | Missing Number ⭐ [B75-268] | XOR | XOR all indices and values | O(n) |
| 7 | Reverse Bits ⭐ [B75-190] | Bit Shift | result = (result<<1) | (n&1), repeat 32× | O(1) |
| 8 | Maximum Subarray ⭐ [B75-53] | Kadane's | curr = max(nums[i], curr+nums[i]) | O(n) |
| 9 | Group Anagrams ⭐ [B75-49] | HashMap+Sort | Sorted string as map key | O(nk log k) |
| 10 | Product Except Self ⭐ [B75-238] | Prefix/Suffix | Prefix pass then suffix variable | O(n) |
| 11 | Max Product Subarray ⭐ [B75-152] | Kadane's Variant | Track max AND min (negatives flip) | O(n) |
| 12 | Longest Palindromic ⭐ [B75-5] | Expand Center | expand(i,i) odd + expand(i,i+1) even | O(n²) |
| 13 | Palindromic Substrings ⭐ [B75-647] | Expand Center | Count per expansion step | O(n²) |
| 14 | Set Matrix Zeroes ⭐ [B75-73] | In-Place Flags | First row/col as markers | O(mn) |
| 15 | Spiral Matrix ⭐ [B75-54] | Boundary Shrink | top/bottom/left/right pointers | O(mn) |
| 16 | Rotate Image ⭐ [B75-48] | In-Place | Transpose + reverse each row | O(n²) |
| 17 | Sum of Two Integers ⭐ [B75-371] | Bit | XOR = sum, AND<<1 = carry | O(1) |
| 18 | Longest Consecutive ⭐ [B75-128] | HashSet | Start-of-sequence detection | O(n) |
When to Use Each Pattern
HashMap / HashSet
- Need O(1) lookup to answer "have I seen X before?" or "does complement exist?"
- Frequency counting: build the map in one pass, query in another
- Grouping: sorted characters or frequency signature as map key
HashSet / Sequential Scan
- Load all values into a HashSet first for O(1) membership checks
- Find the start of a sequence by checking that the predecessor is absent from the set
- Scan forward from each sequence start — each element is processed at most twice across all sequences, giving O(n) total
One-Pass / Kadane's
- Running min/max or running sum that either extends the current window or restarts
- Kadane's:
curr = max(nums[i], curr + nums[i])— prefer restarting if the running sum is negative - For max product: track both max and min because a large negative flips sign
Prefix / Suffix
result[i]depends on the product/sum of elements to its left AND its right- First pass fills prefix into result left-to-right; second pass multiplies in suffix using a running variable right-to-left
Palindrome Expand
- 2n-1 possible centers; try both single-char (odd) and gap (even) for each position
- Expand helper returns length (for longest) or count (for counting)
- Start position from length:
start = center - (len-1)/2
Matrix
- Set Matrix Zeroes: first row/column as markers; record their own zero status beforehand
- Spiral: four boundary pointers shrink inward; check
top ≤ bottomandleft ≤ rightbefore each direction - Rotate 90° clockwise: transpose (swap
[i][j]and[j][i]forj > i) then reverse each row
Bit Manipulation
n & (n-1): clears lowest set bit — count set bits, detect power of 2- XOR: cancels duplicate pairs — find missing/unique number
- AND + left shift: carry in bit addition — sum without arithmetic operators
- Right shift (
>>1): halve a number — use with AND to check last bit
Common Mistakes to Avoid
Array Mistakes
- Kadane's wrong initialization — initialize
currandmaxtonums[0], not 0; an array of all negatives has a max that is negative, not 0 - Max Product Subarray: not saving prev_max before updating — save
tmp = maxbefore computing new max, because the new min formula needs the old max
Matrix Mistakes
- Set Matrix Zeroes: zeroing first row/col before using them as flags — first scan and record
firstRowZero/firstColZero, then use them as markers, then zero them last - Spiral Matrix: extra elements on non-square matrices — always guard the bottom and left passes with
if (top <= bottom)andif (left <= right)respectively
Bit Mistakes
- Counting Bits: using
n/2instead ofn>>1— both work for non-negative, but right shift is the conventional idiom; don't confusen>>1(integer division) withn-1 - Reverse Bits: signed right shift — Java's
>>is signed (fills with sign bit); use>>>for unsigned right shift when shifting the inputnto avoid propagating the sign bit