Why interviewers use small coding questions
Screening and first rounds lean on a compact set of problems because they reveal a lot cheaply: whether you can translate an idea into correct code, handle edge cases without being reminded, and reason about complexity out loud. The problems below recur constantly. What earns the offer is not knowing the answer but the process around it — clarify, state complexity, guard edge cases, then optimise.
Talk while you code. State the approach and its Big-O before typing, name the edge cases you will guard, and when the interviewer asks "can you do better?", trade space for time deliberately rather than guessing.
Q1. Reverse a string without the library reverse.
Convert to a char array and swap from both ends toward the middle — O(n) time, O(n) space for the array. Mentioning new StringBuilder(s).reverse() shows you know the library, but the interviewer usually wants the manual version.
static String reverse(String s) {
if (s == null) return null;
char[] c = s.toCharArray();
int i = 0, j = c.length - 1;
while (i < j) {
char t = c[i]; c[i] = c[j]; c[j] = t;
i++; j--;
}
return new String(c);
}
Interview note: Follow-up: "what about Unicode?" Reversing code units can break surrogate pairs and combining characters; the honest answer is that char-level reversal is fine for ASCII but not fully Unicode-correct.
Q2. Check whether a string is a palindrome.
Two pointers from both ends comparing characters — O(n) time, O(1) extra space. Return false on the first mismatch.
static boolean isPalindrome(String s) {
int i = 0, j = s.length() - 1;
while (i < j) {
if (s.charAt(i++) != s.charAt(j--)) return false;
}
return true;
}
The two-pointer version beats reverse-and-compare because it uses O(1) space and can exit early. If the interviewer adds "ignore case and non-letters", normalise first — that variant is common.
Interview note: Follow-up: "reverse-and-compare vs two-pointer?" Both are O(n) time, but reverse-and-compare allocates a second string (O(n) space) and never short-circuits.
Q3. Find duplicate elements in an array.
Use a HashSet: add each element, and if add returns false it is a duplicate — O(n) time, O(n) space. The naive nested loop is O(n²); leading with the HashSet shows you trade space for time.
static Set<Integer> duplicates(int[] a) {
Set<Integer> seen = new HashSet<>();
Set<Integer> dups = new HashSet<>();
for (int x : a) {
if (!seen.add(x)) dups.add(x); // add() is false on repeat
}
return dups;
}
Using add()'s boolean return instead of a separate contains call is the small idiom that reads as fluency.
Interview note: Follow-up: "the values are 1..n — can you do it in O(1) space?" Yes — cyclic sort or negating the value at the index each number points to, an in-place trick worth naming.
Q4. Check if two strings are anagrams.
Count character frequencies and compare — O(n) time, O(1) space for a fixed alphabet. Sorting both and comparing is O(n log n) and acceptable but slower.
static boolean isAnagram(String a, String b) {
if (a.length() != b.length()) return false;
int[] freq = new int[26];
for (int i = 0; i < a.length(); i++) {
freq[a.charAt(i) - 'a']++;
freq[b.charAt(i) - 'a']--;
}
for (int f : freq) if (f != 0) return false;
return true;
}
The length short-circuit and the single-array increment/decrement trick are the details that make this clean. For arbitrary Unicode, swap the fixed array for a HashMap<Character,Integer>.
Interview note: Trap: "your array assumes lowercase a-z." Correct — state that assumption; for full Unicode use a map keyed by code point.
Q5. Find the missing number in 1..n.
Sum 1..n with n*(n+1)/2 and subtract the actual sum — O(n) time, O(1) space. XOR of all indices and values is the overflow-safe alternative.
static int missing(int[] a, int n) {
long expected = (long) n * (n + 1) / 2; // long guards overflow
long actual = 0;
for (int x : a) actual += x;
return (int) (expected - actual);
}
The long cast is the interview-grade detail: for large n, n*(n+1)/2 overflows int silently. Mentioning the XOR approach (missing = 0 ^ 1 ^ ... ^ n ^ a[0] ^ ...) shows range.
Interview note: Follow-up: "what if two numbers are missing?" Sum gives their total and sum-of-squares gives another equation — two equations, two unknowns.
Q6. Print the Fibonacci sequence efficiently.
Iterate with two rolling variables — O(n) time, O(1) space. Naive recursion is O(2ⁿ) and will be the interviewer's trap; memoization or the iterative form is the expected fix.
static long fib(int n) {
if (n < 2) return n;
long prev = 0, curr = 1;
for (int i = 2; i <= n; i++) {
long next = prev + curr;
prev = curr; curr = next;
}
return curr;
}
Naming why plain recursion is exponential — the same subproblems recomputed across the call tree — is often the real question hiding behind "write Fibonacci."
Interview note: Follow-up: "recursion vs iteration here?" Recursion is O(2ⁿ) and risks stack overflow; iteration is O(n)/O(1). Memoized recursion is O(n) but still uses stack and a cache.
Q7. Count the frequency of characters (and the Streams version).
A HashMap accumulating counts is the direct O(n) solution. The modern Java answer uses groupingBy with counting, which is worth showing to demonstrate library fluency.
// classic
Map<Character, Integer> f = new HashMap<>();
for (char c : s.toCharArray()) f.merge(c, 1, Integer::sum);
// streams
Map<Character, Long> f2 = s.chars()
.mapToObj(c -> (char) c)
.collect(Collectors.groupingBy(c -> c, Collectors.counting()));
merge(c, 1, Integer::sum) is the clean way to increment a map count in one call. Showing both the loop and the Stream signals you can pick the right tool.
Interview note: Trap: "the Streams
chars()gives ints." Right — it is anIntStream; you must box toCharacterbefore grouping, which candidates often forget.
Q8. Find the second largest element in an array.
One pass tracking the largest and second largest — O(n) time, O(1) space. Sorting is O(n log n) and wasteful for a single query.
static int secondLargest(int[] a) {
int max = Integer.MIN_VALUE, second = Integer.MIN_VALUE;
for (int x : a) {
if (x > max) { second = max; max = x; }
else if (x > second && x != max) { second = x; }
}
return second;
}
The x != max guard handles duplicates of the maximum, which is the edge case interviewers plant. Ask whether duplicates count as distinct before coding — that clarification earns credit on its own.
Interview note: Follow-up: "what if the array has fewer than two distinct values?" Decide and state it — return a sentinel, throw, or clarify the contract; silently returning
MIN_VALUEis a bug.
How to prepare
Solve each of these on paper first, then type them and run them against the nasty inputs: empty and null, a single element, all-duplicates, and values large enough to overflow int. The overflow and duplicate cases are where interviewers separate careful engineers from happy-path coders, so build the habit of naming edge cases before you write the loop. Then redo two or three with the Streams API so you can offer both a clear algorithm and its idiomatic library form.
Pair this with the Java Streams questions to sharpen the functional versions, and with how HashMap works internally since hashing underlies the duplicate, anagram and frequency solutions. For structured drilling with follow-up pressure, work through the Java learning path and rehearse talking through complexity out loud.
Frequently Asked Questions
What Java coding questions come up most in first rounds?
Should I solve coding questions with loops or Streams?
How important is complexity analysis in a Java coding round?
Do interviewers care about edge cases in coding questions?
Are these coding questions only for freshers?
Want to Build Your Career in Java Full Stack with AI?
Join CodeBegun and train with working industry engineers — Check the Java Full Stack training details

