Title: Find the Leader Elements in an Array
In this guide, you’ll learn how to find the leader elements in an array using Java. An element is called a leader if it is strictly greater than every element to its right, and by definition the last element of the array is always a leader. This problem shows up often in coding interviews because it tests whether you can think about an array from the right side instead of the usual left-to-right scan.
We’ll walk through a clean, single-pass approach that scans the array from the end, build a complete working Java program, trace the algorithm on a sample input, and cover the common mistakes, edge cases, and interview follow-up questions you should be ready for.
Understanding the Problem
Given an array of integers, a leader is any element that is greater than all the elements that appear after it in the array. The rightmost element never has anything to its right, so it is always a leader.
For example, in the array [16, 17, 4, 3, 5, 2], the leaders are 17, 5, and 2. The value 17 is greater than everything after it, 5 is greater than 3 and 2, and 2 is the last element, so it qualifies automatically.
A naive approach checks, for every index, whether it is greater than all elements to its right, which costs O(n^2) time. The goal is to find all leaders in a single O(n) pass.
Approach / Algorithm Steps
The key insight is that the last element is always a leader, and every leader to its left must beat the best leader found so far. That lets you scan backward while tracking a single running maximum.
- Handle the trivial case: if the array is
nullor empty, return an empty leaders list immediately. - Initialize
maxFromRightto the last element of the array, since the last element is always a leader. - Add that last element to the leaders list.
- Walk the array backward from the second-to-last index down to index 0.
- At each index, compare
numbers[i]tomaxFromRight. - If
numbers[i]is strictly greater thanmaxFromRight, updatemaxFromRighttonumbers[i]and add it to the leaders list. - After the loop, reverse the leaders list so it reflects the original left-to-right order, then return it.
Java Program
Here is a complete, compilable Java program that finds and prints the leader elements of an array:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class LeaderElements {
public static List<Integer> findLeaders(int[] numbers) {
List<Integer> leaders = new ArrayList<>();
if (numbers == null || numbers.length == 0) {
return leaders;
}
int maxFromRight = numbers[numbers.length - 1];
leaders.add(maxFromRight);
for (int i = numbers.length - 2; i >= 0; i--) {
if (numbers[i] > maxFromRight) {
maxFromRight = numbers[i];
leaders.add(maxFromRight);
}
}
Collections.reverse(leaders);
return leaders;
}
public static void main(String[] args) {
int[] numbers = {16, 17, 4, 3, 5, 2};
List<Integer> leaders = findLeaders(numbers);
System.out.println("Leaders: " + leaders);
}
}Explanation of the Program
maxFromRightstarts out holding the last element, since the last element is always a leader.- The loop in
findLeaderswalks backward from the second-to-last index down to index 0. - Whenever
numbers[i]is strictly greater than the running maximum, it becomes the newmaxFromRightand is recorded as a leader. - Elements that are not greater than
maxFromRightare simply skipped, since a larger element already exists to their right. - Because leaders are discovered from right to left,
Collections.reverse(leaders)restores the original left-to-right order before the list is returned.
Step-by-Step Trace
Let’s trace findLeaders on the input [4, 2, 9, 5, 8, 1, 6], which should produce the leaders [9, 8, 6]. The scan starts with maxFromRight set to the last element, 6, and then walks backward from index 5 down to index 0.
| Iteration | numbers[i] | maxFromRight (before) | numbers[i] > maxFromRight? | maxFromRight (after) |
|---|---|---|---|---|
| 1 | 1 | 6 | no | 6 |
| 2 | 8 | 6 | yes | 8 |
| 3 | 5 | 8 | no | 8 |
| 4 | 9 | 8 | yes | 9 |
| 5 | 2 | 9 | no | 9 |
| 6 | 4 | 9 | no | 9 |
At the end of each iteration, maxFromRight holds the maximum of numbers[i..numbers.length - 1], so any value that updates it is guaranteed to be a leader.
Examples
Example 1: Mixed Values
A typical array with a mix of small and large values:
int[] numbers = {16, 17, 4, 3, 5, 2};
List<Integer> leaders = findLeaders(numbers);
System.out.println(leaders);
// Output: [17, 5, 2]Example 2: Strictly Decreasing Array
When every element is smaller than the one before it, every element is a leader:
int[] numbers = {9, 8, 7, 6, 5};
List<Integer> leaders = findLeaders(numbers);
System.out.println(leaders);
// Output: [9, 8, 7, 6, 5]Example 3: Strictly Increasing Array
When every element is larger than the one before it, only the last element can be a leader:
int[] numbers = {1, 2, 3, 4, 5};
List<Integer> leaders = findLeaders(numbers);
System.out.println(leaders);
// Output: [5]Common Mistakes to Avoid
These are the mistakes most candidates make the first time they solve this problem:
- Scanning left to right – tracking a running maximum from the left finds elements greater than everything before them, which is a different problem entirely, not leaders. Scan from the right so each comparison looks only at elements that come after the current index.
- Starting the loop at the last index – comparing the last element to itself wastes a step and risks double-counting it. Initialize
maxFromRighttonumbers[numbers.length - 1], add it to the list, then start the loop atnumbers.length - 2. - Using >= instead of > – when duplicate values tie the current maximum, a
>=comparison reports every tied occurrence as a separate leader, so{3, 3, 3}would wrongly return[3, 3, 3]instead of just[3]. Use a strict>so only the rightmost occurrence of the maximum counts. - Forgetting to reverse the result – leaders are discovered from right to left, so returning the list as built prints them in the reverse of their original array order. Call
Collections.reverse(leaders)before returning, or insert each new leader at index 0 as you go.
Edge Cases to Test
Walk through these boundary inputs before you call the solution finished:
- Empty array
- Single-element array
- Strictly increasing array (only the last element is a leader)
- Strictly decreasing array (every element is a leader)
- All identical elements
- Negative numbers present
- Integer.MIN_VALUE or Integer.MAX_VALUE present
- Null array reference
Additional Considerations
The algorithm runs in O(n) time, since it visits each element exactly once while scanning from the right. Extra space is O(1) beyond the output list itself, because only a single maxFromRight variable is needed to track the running maximum.
Integer.MAX_VALUE deserves attention because once maxFromRight reaches it, no element further to the left can ever become a new leader, so the rest of the backward scan only performs comparisons without updating the result. Integer.MIN_VALUE is worth testing too, since it is a valid array value but would never itself become a leader unless it is the very last element.
If you want to avoid the final Collections.reverse call, you can insert each newly found leader at the front of a LinkedList instead of appending to an ArrayList. That trades an O(n) reversal for O(1) insertions at the head, with a small constant-factor cost per insertion.
Interview Follow-up Questions
Be ready for an interviewer to push past the base problem with questions like these:
- What if the array is already sorted in non-decreasing order? – the array has exactly one leader, the last element, so you can skip the scan entirely and return
numbers[numbers.length - 1]in O(1). - What if you need elements greater than everything before them instead? – that is the prefix-maxima variant; run a single left-to-right pass tracking a running maximum the same way, just flip which side you compare against.
- What if the array arrives as a stream of unknown length and you cannot look ahead? – leader status depends on elements that have not arrived yet, so you cannot finalize any leader until the stream ends; buffer the values or make a second pass once the stream closes.
- What if you need the top K leaders by value instead of all of them? – combine the right-to-left scan with a min-heap of size K to keep only the K largest leaders seen so far, which changes the complexity to O(n log K).
- What if you must find the leaders using O(1) extra memory and cannot allocate a result list? – print each leader as soon as it is discovered during the backward scan instead of storing it, and let the caller reverse the printed order if the original left-to-right order is required.
Conclusion
Finding leader elements is a great example of flipping your perspective on an array problem: scanning from the right turns an apparently quadratic comparison into a single linear pass. Once you’re comfortable with the right-to-left running maximum pattern shown here, you’ll start recognizing it in other problems that ask about visibility, dominance, or “everything after this point” conditions.
Try adapting findLeaders to return indices instead of values, or to operate on a List<Integer> input instead of a primitive array, to make sure you really understand why the right-to-left scan works.
You can learn more about array-based interview problems like this one in the Arrays category on Daily Java Concept.



