Java Challenges for Every Career Stage
Navigating a career in software development means constantly growing your skills. Whether you’re a junior developer just starting out, a mid-level engineer looking to advance, or a senior dev keeping your skills sharp, targeted practice is key. For hiring managers, it’s about finding the right challenge to assess the right skill level.
That’s exactly what this page is for. We’ve organized 30 Java coding challenges specifically for Junior, Mid-Level, and Senior developers for each level. It’s the perfect way to prepare for your next career move or to find the perfect candidate for your team.
Jump to Your Level
| Junior Developer | Mid-Level Developer | ✈️ Senior Developer |
Junior Developer Challenges
1. Reverse a String
Tests basic string manipulation.
public String reverseString(String s) { return new StringBuilder(s).reverse().toString(); }2. Check for Palindrome
A simple test of string comparison and manipulation.
public boolean isPalindrome(String s) { String reversed = new StringBuilder(s).reverse().toString(); return s.equals(reversed); }3. FizzBuzz
The quintessential test of basic loops and conditionals.
public void fizzBuzz(int n) { for (int i = 1; i <= n; i++) { if (i % 3 == 0 && i % 5 == 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); } }4. Find Maximum in Array
A fundamental array traversal problem.
public int findMax(int[] arr) { int max = arr[0]; for (int i = 1; i < arr.length; i++) { if (arr[i] > max) max = arr[i]; } return max; }5. Sum of Array
A simple loop to practice accumulation.
public int sumArray(int[] arr) { int sum = 0; for (int num : arr) { sum += num; } return sum; }6. Count Vowels in a String
Good for practicing character-by-character string processing.
public int countVowels(String s) { int count = 0; String vowels = "aeiou"; for (char c : s.toLowerCase().toCharArray()) { if (vowels.indexOf(c) != -1) count++; } return count; }7. Factorial of a Number
A classic introduction to recursion.
public int factorial(int n) { if (n <= 1) return 1; return n * factorial(n - 1); }8. Linear Search
Checks for understanding of basic search algorithms.
public int linearSearch(int[] arr, int target) { for (int i = 0; i < arr.length; i++) { if (arr[i] == target) return i; } return -1; }9. Check if Number is Even or Odd
Tests the most basic conditional logic.
public String isEvenOrOdd(int num) { return (num % 2 == 0) ? "Even" : "Odd"; }10. Concatenate Two Arrays
A problem for understanding array creation and manipulation.
public int[] concatArrays(int[] a, int[] b) { int[] result = new int[a.length + b.length]; System.arraycopy(a, 0, result, 0, a.length); System.arraycopy(b, 0, result, a.length, b.length); return result; }Mid-Level Developer Challenges
1. Two Sum
The classic interview question to test knowledge of HashMaps.
public int[] twoSum(int[] nums, int target) { java.util.Map map = new java.util.HashMap<>(); 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); } throw new IllegalArgumentException("No two sum solution"); } 2. Valid Parentheses
A perfect problem for demonstrating the use of a Stack.
public boolean isValid(String s) { java.util.Stack stack = new java.util.Stack<>(); for (char c : s.toCharArray()) { if (c == '(') stack.push(')'); else if (c == '{') stack.push('}'); else if (c == '[') stack.push(']'); else if (stack.isEmpty() || stack.pop() != c) return false; } return stack.isEmpty(); } 3. Binary Search in Sorted Array
Tests understanding of efficient search algorithms.
public int search(int[] nums, int target) { int left = 0, right = nums.length - 1; while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target) return mid; if (nums[mid] < target) left = mid + 1; else right = mid - 1; } return -1; }4. Group Anagrams
Requires creative use of HashMaps and sorting to group words.
public java.util.List> groupAnagrams(String[] strs) { java.util.Map> map = new java.util.HashMap<>(); for (String s : strs) { char[] ca = s.toCharArray(); java.util.Arrays.sort(ca); String key = String.valueOf(ca); if (!map.containsKey(key)) map.put(key, new java.util.ArrayList<>()); map.get(key).add(s); } return new java.util.ArrayList<>(map.values()); } 5. Longest Substring Without Repeating Characters
A sliding window problem that tests dynamic substring analysis.
public int lengthOfLongestSubstring(String s) { java.util.Map map = new java.util.HashMap<>(); int start = 0, maxLen = 0; for (int end = 0; end < s.length(); end++) { char c = s.charAt(end); if (map.containsKey(c)) { start = Math.max(map.get(c) + 1, start); } map.put(c, end); maxLen = Math.max(maxLen, end - start + 1); } return maxLen; } 6. Implement a Queue using Stacks
Tests knowledge of data structure properties and how to simulate one with another.
class MyQueue { java.util.Stack s1 = new java.util.Stack<>(); java.util.Stack s2 = new java.util.Stack<>(); public void push(int x) { while (!s1.isEmpty()) s2.push(s1.pop()); s1.push(x); while (!s2.isEmpty()) s1.push(s2.pop()); } public int pop() { return s1.pop(); } } 7. Binary Tree Level Order Traversal
A classic tree traversal problem best solved with a Queue (BFS).
public java.util.List> levelOrder(TreeNode root) { java.util.List> res = new java.util.ArrayList<>(); if (root == null) return res; java.util.Queue queue = new java.util.LinkedList<>(); queue.add(root); while (!queue.isEmpty()) { int levelSize = queue.size(); java.util.List currentLevel = new java.util.ArrayList<>(); for (int i = 0; i < levelSize; i++) { TreeNode node = queue.poll(); currentLevel.add(node.val); if (node.left != null) queue.add(node.left); if (node.right != null) queue.add(node.right); } res.add(currentLevel); } return res; } 8. Product of Array Except Self
A tricky array problem that can be solved efficiently without division.
public int[] productExceptSelf(int[] nums) { int n = nums.length; int[] res = new int[n]; res[0] = 1; for (int i = 1; i < n; i++) { res[i] = res[i - 1] * nums[i - 1]; } int right = 1; for (int i = n - 1; i >= 0; i--) { res[i] *= right; right *= nums[i]; } return res; }9. Rotate Image
An in-place matrix manipulation problem requiring careful indexing.
public void rotate(int[][] matrix) { int n = matrix.length; for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) { int temp = matrix[i][j]; matrix[i][j] = matrix[j][i]; matrix[j][i] = temp; } } for (int i = 0; i < n; i++) { for (int j = 0; j < n / 2; j++) { int temp = matrix[i][j]; matrix[i][j] = matrix[i][n - 1 - j]; matrix[i][n - 1 - j] = temp; } } }10. Find First and Last Position of Element in Sorted Array
Requires a modified binary search to find the boundaries of a target element.
public int[] searchRange(int[] nums, int target) { int[] result = new int[]{-1, -1}; result[0] = findPosition(nums, target, true); if (result[0] != -1) { result[1] = findPosition(nums, target, false); } return result; } private int findPosition(int[] nums, int target, boolean first) { int idx = -1, start = 0, end = nums.length - 1; while (start <= end) { int mid = start + (end - start) / 2; if (target < nums[mid]) end = mid - 1; else if (target > nums[mid]) start = mid + 1; else { idx = mid; if (first) end = mid - 1; else start = mid + 1; } } return idx; }Senior Developer Challenges
1. Merge K Sorted Lists
Tests efficient merging using a Min-Heap (PriorityQueue).
public ListNode mergeKLists(ListNode[] lists) { java.util.PriorityQueue heap = new java.util.PriorityQueue<>((a, b) -> a.val - b.val); for (ListNode node : lists) if (node != null) heap.add(node); ListNode dummy = new ListNode(); ListNode tail = dummy; while (!heap.isEmpty()) { tail.next = heap.poll(); tail = tail.next; if (tail.next != null) heap.add(tail.next); } return dummy.next; } 2. Trapping Rain Water
A classic problem requiring an optimal two-pointer approach.
public int trap(int[] height) { int l = 0, r = height.length - 1, lMax = 0, rMax = 0, water = 0; while (l < r) { if (height[l] < height[r]) { if (height[l] >= lMax) lMax = height[l]; else water += lMax - height[l]; l++; } else { if (height[r] >= rMax) rMax = height[r]; else water += rMax - height[r]; r--; } } return water; }3. Word Break
A dynamic programming problem testing string segmentation.
public boolean wordBreak(String s, java.util.List wordDict) { boolean[] dp = new boolean[s.length() + 1]; dp[0] = true; for (int i = 1; i <= s.length(); i++) { for (int j = 0; j < i; j++) { if (dp[j] && wordDict.contains(s.substring(j, i))) { dp[i] = true; break; } } } return dp[s.length()]; } 4. LRU Cache
A system design problem requiring a combination of a HashMap and a Doubly Linked List.
class LRUCache { private java.util.Map map; private Node head, tail; private int capacity; class Node { int key, val; Node prev, next; } public LRUCache(int capacity) { this.capacity = capacity; map = new java.util.HashMap<>(); head = new Node(); tail = new Node(); head.next = tail; tail.prev = head; } public int get(int key) { if (!map.containsKey(key)) return -1; Node node = map.get(key); moveToHead(node); return node.val; } private void moveToHead(Node node) { /* ... */ } } 5. Find Median from Data Stream
Requires balancing two heaps to maintain the median in real-time.
class MedianFinder { java.util.PriorityQueue lo = new java.util.PriorityQueue<>(java.util.Collections.reverseOrder()); java.util.PriorityQueue hi = new java.util.PriorityQueue<>(); public void addNum(int num) { lo.add(num); hi.add(lo.poll()); if (lo.size() < hi.size()) lo.add(hi.poll()); } public double findMedian() { return lo.size() > hi.size() ? lo.peek() : (lo.peek() + hi.peek()) * 0.5; } } 6. Number of Islands
A graph traversal problem on a grid, typically solved with DFS or BFS.
public int numIslands(char[][] grid) { int count = 0; for (int i = 0; i < grid.length; i++) { for (int j = 0; j < grid[0].length; j++) { if (grid[i][j] == '1') { dfs(grid, i, j); count++; } } } return count; } void dfs(char[][] grid, int r, int c) { if (r < 0 || c < 0 || r >= grid.length || c >= grid[0].length || grid[r][c] == '0') return; grid[r][c] = '0'; dfs(grid, r + 1, c); dfs(grid, r - 1, c); dfs(grid, r, c + 1); dfs(grid, r, c - 1); }7. Longest Palindromic Substring
A dynamic programming problem or can be solved with an "expand from center" approach.
public String longestPalindrome(String s) { if (s == null || s.length() < 1) return ""; int start = 0, end = 0; for (int i = 0; i < s.length(); i++) { int len1 = expand(s, i, i); int len2 = expand(s, i, i + 1); int len = Math.max(len1, len2); if (len > end - start) { start = i - (len - 1) / 2; end = i + len / 2; } } return s.substring(start, end + 1); } 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; }8. Coin Change
A classic dynamic programming problem to find the minimum number of coins for a given amount.
public int coinChange(int[] coins, int amount) { int[] dp = new int[amount + 1]; java.util.Arrays.fill(dp, amount + 1); dp[0] = 0; for (int i = 1; i <= amount; i++) { for (int coin : coins) { if (coin <= i) { dp[i] = Math.min(dp[i], dp[i - coin] + 1); } } } return dp[amount] > amount ? -1 : dp[amount]; }9. Implement Trie (Prefix Tree)
Tests knowledge of specialized tree data structures for efficient string searching.
class Trie { class TrieNode { TrieNode[] children = new TrieNode[26]; boolean isEnd = false; } TrieNode root; public Trie() { root = new TrieNode(); } public 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; } /* ... search and startsWith methods ... */ }10. Regular Expression Matching
A highly complex dynamic programming problem involving pattern matching logic.
public boolean isMatch(String s, String p) { boolean[][] dp = new boolean[s.length() + 1][p.length() + 1]; dp[0][0] = true; for (int j = 1; j <= p.length(); j++) { if (p.charAt(j - 1) == '*') dp[0][j] = dp[0][j - 2]; } for (int i = 1; i <= s.length(); i++) { for (int j = 1; j <= p.length(); j++) { if (p.charAt(j - 1) == '.' || p.charAt(j-1) == s.charAt(i-1)) dp[i][j] = dp[i-1][j-1]; else if (p.charAt(j-1) == '*') { dp[i][j] = dp[i][j-2]; if (p.charAt(j-2)=='.' || p.charAt(j-2)==s.charAt(i-1)) dp[i][j] |= dp[i-1][j]; } } } return dp[s.length()][p.length()]; }Tips to Prepare for Java Coding Challenges
- Strengthen Your Fundamentals: Before diving into complex problems, ensure your understanding of core concepts like loops, control flow, and data types is solid.
- Practice in Realistic Conditions: Code on a whiteboard or a simple text editor to get used to working without autocomplete. Participating in timed challenges and mock interviews can also help you manage pressure and anxiety.
- Stay Updated: Keep up with modern Java features such as Streams, Lambdas, and the Optional class, as interviewers often look for knowledge of current best practices.
- Learn Common Patterns: Familiarize yourself with widely used patterns like sliding windows, recursion, and dynamic programming. Recognizing these can help you quickly identify a path to a solution.
- Engage with the Community: Join forums like Stack Overflow or online communities to learn new problem-solving techniques and stay connected with other developers.
- Test Your Limits: Participate in coding contests to practice in high-pressure scenarios and challenge your limits.
Conclusion
Every top developer started exactly where you are right now. While these challenges might seem intimidating at first, consistent practice will help you recognize patterns, build problem-solving instincts, and ultimately excel in your interviews. Happy coding!


