Intro
If you are preparing for a Java interview, the same handful of questions appear again and again — across service companies, product firms, and campus placements. This guide collects the fifteen that come up most, grouped by the kind of thinking each one tests. For every question you get working code, the output it produces, the time and space complexity, and — because the people setting these questions read guides too — a short note on what a strong answer actually signals.
The first five are covered in depth, including the optimised alternative an interviewer is usually steering you toward. The remaining ten are tighter: the working solution and the one insight that matters.
How interviewers read a Java answer
When an interviewer poses a coding question, they are reading four layers, roughly in this order:
| Layer | What a weaker answer does | What a stronger answer does |
| Correctness | Solves the happy path; misses empty input, nulls, or case | Names the edge cases before coding and handles them |
| Efficiency | Ships the first idea that works, usually a nested loop | States the complexity, then reaches for the O(n) approach and explains why |
| Idiom | Hand-rolls loops for things the library already does | Uses StringBuilder, the Collections framework, and Stream/Collectors, and explains the trade-off |
| Communication | Codes in silence, presents a finished block | Thinks out loud, so the interviewer sees the reasoning |
1How do you reverse a string in Java?
The classic opener. Java strings are immutable, so it reveals whether you reach for the right mutable-builder idiom or fight the type.
public class ReverseString {
public static String reverseString(String text) {
return new StringBuilder(text).reverse().toString();
}
public static void main(String[] args) {
String text = "interview";
System.out.println(reverseString(text)); // weivretni
}
}StringBuilder.reverse() mutates an internal char array in place and only allocates once, on toString(). O(n) time, O(n) space. Naive alternative that also works, but allocates a new String on every concatenation inside the loop:
public class ReverseStringNaive {
public static String reverseStringNaive(String text) {
String reversed = "";
for (int i = text.length() - 1; i >= 0; i--) {
reversed += text.charAt(i); // O(n) per concatenation -> O(n²) overall
}
return reversed;
}
public static void main(String[] args) {
System.out.println(reverseStringNaive("interview")); // weivretni
}
}What this evaluates: idiom. Reaching for StringBuilder signals you know Java strings are immutable and why repeated += in a loop is a red flag; the manual loop signals someone who hasn't internalised that yet.
2How do you check whether a string is a palindrome?
public class PalindromeCheck {
public static boolean isPalindrome(String text) {
String cleaned = text.toLowerCase().replace(" ", "");
return cleaned.equals(new StringBuilder(cleaned).reverse().toString());
}
public static void main(String[] args) {
System.out.println(isPalindrome("Race car")); // true
System.out.println(isPalindrome("hello")); // false
}
}The judgment is in the cleaning step. A strong candidate asks whether case and spaces should be ignored before coding. O(n) time, O(n) space.
What this evaluates: correctness / edge-case awareness. The clarifying question is worth more than the code.
3How do you count the vowels in a string?
public class CountVowels {
public static long countVowels(String text) {
String vowels = "aeiou";
return text.toLowerCase().chars()
.filter(c -> vowels.indexOf(c) >= 0)
.count();
}
public static void main(String[] args) {
System.out.println(countVowels("Education")); // 5
}
}chars() streams the string lazily — no intermediate array is materialised. Compare against pre-materialising with toCharArray():
| Approach | Memory | When it matters |
text.chars().filter(...).count() — stream | O(1) extra | Large strings; preferred |
text.toCharArray() then loop | O(n) extra | Same result, allocates the full array up front |
What this evaluates: idiom and memory. The follow-up — "what if the string is a gigabyte?" — is where the stream answer shows you understand lazy evaluation over eager materialisation.
4How do you find the first non-repeating character in a string?
import java.util.LinkedHashMap;
import java.util.Map;
public class FirstUniqueCharacter {
public static Character firstUnique(String text) {
Map<Character, Integer> counts = new LinkedHashMap<>();
for (char c : text.toCharArray()) {
counts.merge(c, 1, Integer::sum);
}
for (char c : text.toCharArray()) {
if (counts.get(c) == 1) return c;
}
return null;
}
public static void main(String[] args) {
System.out.println(firstUnique("swiss")); // w
}
}Two passes, O(n) total. The naive version calls text.indexOf(c) == text.lastIndexOf(c) inside the loop — each call rescans the string, making it O(n²).
What this evaluates: efficiency. Both return 'w'; the signal is noticing the hidden O(n²) in the naive check and reaching for a single count pass to make it O(n) — said out loud.
5How do you check if two strings are anagrams?
public class AnagramCheck {
public static boolean isAnagram(String a, String b) {
if (a.length() != b.length()) return false;
int[] counts = new int[26];
for (char c : a.toCharArray()) counts[c - 'a']++;
for (char c : b.toCharArray()) counts[c - 'a']--;
for (int n : counts) if (n != 0) return false;
return true;
}
public static void main(String[] args) {
System.out.println(isAnagram("listen", "silent")); // true
System.out.println(isAnagram("hello", "world")); // false
}
}A fixed 26-slot frequency array checks counts in one O(n) pass, no extra allocation beyond the array. The commonly-taught alternative sorts both strings:
import java.util.Arrays;
public class AnagramCheckSorted {
public static boolean isAnagramSorted(String a, String b) {
char[] ca = a.toCharArray();
char[] cb = b.toCharArray();
Arrays.sort(ca);
Arrays.sort(cb);
return Arrays.equals(ca, cb); // correct, but O(n log n)
}
public static void main(String[] args) {
System.out.println(isAnagramSorted("listen", "silent")); // true
System.out.println(isAnagramSorted("hello", "world")); // false
}
}| Approach | Time | Note |
int[26] frequency count | O(n) | Counts once, compares |
Arrays.sort both | O(n log n) | Shorter to write, slower at scale |
What this evaluates: efficiency + idiom. Naming the trade-off unprompted — "sorting works and is O(n log n), but a frequency array gets it to O(n)" — is the senior signal.
6FizzBuzz
public class FizzBuzz {
public static void fizzBuzz(int limit) {
for (int i = 1; i <= limit; i++) {
if (i % 15 == 0) System.out.println("FizzBuzz");
else if (i % 3 == 0) System.out.println("Fizz");
else if (i % 5 == 0) System.out.println("Buzz");
else System.out.println(i);
}
}
public static void main(String[] args) {
fizzBuzz(15);
// 1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz
}
}The trap: check i % 15 first. Evaluates: correctness and ordering of conditions.
7Fibonacci sequence
import java.util.ArrayList;
import java.util.List;
public class Fibonacci {
public static List<Integer> fib(int n) {
List<Integer> result = new ArrayList<>();
int a = 0, b = 1;
for (int i = 0; i < n; i++) {
result.add(a);
int next = a + b;
a = b;
b = next;
}
return result;
}
public static void main(String[] args) {
System.out.println(fib(8)); // [0, 1, 1, 2, 3, 5, 8, 13]
}
}The swap via a next temp is the clean iterative move. Iterative O(n) vs naive recursion O(2ⁿ). Evaluates: idiom; avoiding exponential recursion.
8Remove duplicates, keep order
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
public class DuplicatesRemove {
public static List<Integer> dedupe(List<Integer> seq) {
return new ArrayList<>(new LinkedHashSet<>(seq));
}
public static void main(String[] args) {
System.out.println(dedupe(List.of(3, 1, 3, 2, 1, 5))); // [3, 1, 2, 5]
}
}LinkedHashSet preserves first-seen insertion order while dropping duplicates, so the dedupe is one line. O(n). Evaluates: efficiency and knowing which Set implementation preserves order (HashSet would not).
9Most frequent character
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;
public class FreqChar {
public static char maxChar(String text) {
Map<Character, Long> counts = text.chars()
.mapToObj(c -> (char) c)
.collect(Collectors.groupingBy(c -> c, Collectors.counting()));
return Collections.max(counts.entrySet(), Map.Entry.comparingByValue()).getKey();
}
public static void main(String[] args) {
System.out.println(maxChar("aabbbcc")); // b
}
}Evaluates: idiom — knowing Collectors.groupingBy with a downstream counting() collector rather than hand-rolling a HashMap counter loop.
10Two Sum
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class TwoSum {
public static int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> seen = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (seen.containsKey(complement)) {
return new int[]{seen.get(complement), i};
}
seen.put(nums[i], i);
}
return new int[]{};
}
public static void main(String[] args) {
System.out.println(Arrays.toString(twoSum(new int[]{2, 7, 11, 15}, 9))); // [0, 1]
}
}Hashmap, one pass, O(n). Brute force nested loop is O(n²). Evaluates: efficiency — the canonical O(n²) → O(n) with a hashmap.
11Missing number from 1 to n
public class MissingNumber {
public static int missing(int[] nums, int n) {
int expected = n * (n + 1) / 2;
int actual = 0;
for (int num : nums) actual += num;
return expected - actual;
}
public static void main(String[] args) {
System.out.println(missing(new int[]{1, 2, 4, 5}, 5)); // 3
}
}O(n) time, O(1) space. Evaluates: reaching for the maths insight over sorting.
12Reverse words in a sentence
import java.util.Arrays;
import java.util.Collections;
public class ReverseWords {
public static String reverseWords(String sentence) {
String[] words = sentence.trim().split("\\s+");
Collections.reverse(Arrays.asList(words));
return String.join(" ", words);
}
public static void main(String[] args) {
System.out.println(reverseWords("the quick brown fox")); // fox brown quick the
}
}Reverses word order, not characters — and note Arrays.asList is backed by the original array, so Collections.reverse mutates it in place. Evaluates: correctness — clarifying "words" vs "characters", plus awareness of Arrays.asList's fixed-size, array-backed behaviour.
13Balanced parentheses
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Map;
public class BalancedParantheses {
public static boolean isBalanced(String s) {
Deque<Character> stack = new ArrayDeque<>();
Map<Character, Character> pairs = Map.of(')', '(', ']', '[', '}', '{');
for (char c : s.toCharArray()) {
if (c == '(' || c == '[' || c == '{') {
stack.push(c);
} else if (pairs.containsKey(c)) {
if (stack.isEmpty() || stack.pop() != pairs.get(c)) return false;
}
}
return stack.isEmpty();
}
public static void main(String[] args) {
System.out.println(isBalanced("({[]})")); // true
System.out.println(isBalanced("([)]")); // false
}
}O(n). Note ArrayDeque is the recommended stack in modern Java — faster than Stack, which is a legacy synchronized class. Evaluates: data-structure choice — recognising the stack signature and picking the right implementation.
14Flatten a nested list
import java.util.ArrayList;
import java.util.List;
public class FlattenNestedList {
public static List<Integer> flatten(List<?> nested) {
List<Integer> result = new ArrayList<>();
for (Object item : nested) {
if (item instanceof List<?> list) {
result.addAll(flatten(list));
} else {
result.add((Integer) item);
}
}
return result;
}
public static void main(String[] args) {
System.out.println(flatten(List.of(1, List.of(2, List.of(3, 4), 5)))); // [1, 2, 3, 4, 5]
}
}Uses a Java 16+ pattern-matching instanceof to check and cast in one step. Evaluates: recognising arbitrary nesting needs recursion, plus comfort with instanceof pattern matching over the older cast-after-check style.
15Word frequency
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
public class WordFrequency {
public static Map<String, Long> wordFrequency(String text) {
return Arrays.stream(text.split(" "))
.collect(Collectors.groupingBy(w -> w, Collectors.counting()));
}
public static void main(String[] args) {
Map<String, Long> freq = wordFrequency("the cat sat on the mat the cat");
System.out.println(freq.get("the")); // 3
System.out.println(freq.get("cat")); // 2
}
}Evaluates: idiom - reusing the groupingBy/counting() collector pair across problem shapes, the same move as Q9.
Frequently Asked Questions
What are the most common Java coding interview questions?
HashMap or Collectors.groupingBy), array/number logic (Two Sum, missing number), and structure problems (balanced parentheses, flattening nested lists). The fifteen here cover the patterns behind nearly all of them.