Introduction
Finding the smallest and largest digit in a number is another classic Java programming exercise that builds upon the digit extraction techniques you've already learned throughout this series.
The core idea is simple:
- Extract one digit at a time.
- Compare it with the smallest and largest values found so far.
- Update those values whenever necessary.
Although the algorithm itself is straightforward, it introduces an important programming pattern known as running comparison, where values are continuously updated while processing data sequentially.
This technique appears in many real-world algorithms, including:
- Finding the maximum or minimum value in an array
- Determining the highest or lowest score
- Processing sensor data
- Statistical calculations
In this guide, you'll learn:
- Finding the smallest and largest digit using manual comparisons
- Using Java's built-in
Math.max()andMath.min()methods - Handling negative numbers correctly
- A recursive implementation
- Finding the second largest digit as an interview extension
Understanding the Problem
Suppose the input number is:
6392
Its individual digits are:
6
3
9
2
Among these:
- Largest digit = 9
- Smallest digit = 2
To determine these values, every digit must be examined exactly once.
While processing each digit, we continuously maintain two variables:
largestsmallest
Whenever a digit is larger than the current maximum, we update largest.
Whenever a digit is smaller than the current minimum, we update smallest.
This approach avoids sorting and requires only a single pass through the digits.
Method 1: Using a While Loop with Manual Comparison
This is the standard approach and the one most commonly asked in interviews.
The algorithm repeatedly extracts digits using modulus and division while updating the smallest and largest values.
Java Program
public class SmallestLargestDigit {
public static void main(String[] args) {
int num = 6392;
int largest = Integer.MIN_VALUE;
int smallest = Integer.MAX_VALUE;
while (num != 0) {
int digit = num % 10;
if (digit > largest) {
largest = digit;
}
if (digit < smallest) {
smallest = digit;
}
num = num / 10;
}
System.out.println("Largest digit: " + largest);
System.out.println("Smallest digit: " + smallest);
}
}
Output
Largest digit: 9
Smallest digit: 2
Step-by-Step Execution
Let the input be:
6392
Initially:
| Variable | Value |
|---|---|
| largest | Integer.MIN_VALUE |
| smallest | Integer.MAX_VALUE |
Iteration 1
Current number:
6392
Extract digit:
2
Update:
largest = 2
smallest = 2
Remaining number:
639
Iteration 2
Current number:
639
Extract digit:
9
Comparison:
9 > 2
Update:
largest = 9
Smallest remains:
2
Remaining number:
63
Iteration 3
Current number:
63
Extract digit:
3
Comparisons:
3 > 9 → No
3 < 2 → No
No updates occur.
Remaining number:
6
Iteration 4
Current number:
6
Extract digit:
6
Comparisons:
6 > 9 → No
6 < 2 → No
No updates occur.
The remaining number becomes:
0
The loop terminates.
Final values:
Largest digit = 9
Smallest digit = 2
Why Use Integer.MIN_VALUE and Integer.MAX_VALUE?
Notice the initialization:
int largest = Integer.MIN_VALUE;
int smallest = Integer.MAX_VALUE;
These constants represent the smallest and largest possible values that an int can store.
This guarantees that the very first digit processed will always update both variables correctly.
For example, if the first extracted digit is:
7
then:
7 > Integer.MIN_VALUE
is always true.
Similarly:
7 < Integer.MAX_VALUE
is also always true.
This makes the algorithm reliable regardless of the first digit encountered.
Time Complexity
- Time Complexity: O(d)
- Space Complexity: O(1)
where d is the number of digits in the input number.
Method 2: Using Math.max() and Math.min()
Java provides built-in utility methods that simplify comparisons.
Instead of writing explicit if statements, we can use:
Math.max()Math.min()
to update the tracking variables.
Java Program
public class SmallestLargestUsingMath {
public static void main(String[] args) {
int num = 6392;
int largest = Integer.MIN_VALUE;
int smallest = Integer.MAX_VALUE;
while (num != 0) {
int digit = num % 10;
largest = Math.max(largest, digit);
smallest = Math.min(smallest, digit);
num = num / 10;
}
System.out.println("Largest digit: " + largest);
System.out.println("Smallest digit: " + smallest);
}
}
Output
Largest digit: 9
Smallest digit: 2
How It Works
Instead of writing:
if (digit > largest) {
largest = digit;
}
we simply write:
largest = Math.max(largest, digit);
Similarly,
instead of:
if (digit < smallest) {
smallest = digit;
}
we write:
smallest = Math.min(smallest, digit);
Both approaches produce identical results.
The difference is only in readability.
Which Approach Should You Choose?
Both methods have:
- The same algorithm
- The same time complexity
- The same memory usage
The Math.max() / Math.min() version is generally preferred in production code because it is shorter, cleaner, and easier to read.
However, beginners often find the manual comparison version easier to understand because it clearly shows each comparison step.
Time Complexity
- Time Complexity: O(d)
- Space Complexity: O(1)
where d is the number of digits in the input number.
Method 3: Using Recursion
The same logic used in the iterative solution can also be implemented using recursion.
Instead of processing each digit inside a loop, each recursive call processes one digit and then calls itself with the remaining part of the number.
Java Program
public class SmallestLargestRecursion {
static int largest = Integer.MIN_VALUE;
static int smallest = Integer.MAX_VALUE;
static void findDigits(int num) {
if (num == 0) {
return;
}
int digit = num % 10;
largest = Math.max(largest, digit);
smallest = Math.min(smallest, digit);
findDigits(num / 10);
}
public static void main(String[] args) {
int num = 6392;
findDigits(num);
System.out.println("Largest digit: " + largest);
System.out.println("Smallest digit: " + smallest);
}
}
Output
Largest digit: 9
Smallest digit: 2
How It Works
Suppose the input is:
6392
The recursive calls occur as follows:
findDigits(6392)
↓
digit = 2
↓
findDigits(639)
↓
digit = 9
↓
findDigits(63)
↓
digit = 3
↓
findDigits(6)
↓
digit = 6
↓
findDigits(0)
The base case:
if (num == 0)
stops the recursion.
Throughout this process, the static variables largest and smallest are continuously updated.
Design Limitation
Like several earlier recursive examples in this series, this solution uses static variables.
That means:
largest
smallest
retain their values even after the method finishes.
If the method is called again without resetting these variables, incorrect results may occur.
A cleaner production-quality solution would pass these values through recursive parameters or return an object containing both values.
Time Complexity
- Time Complexity: O(d)
- Space Complexity: O(d)
where d is the number of digits.
Method 4: Handling Negative Numbers Correctly
Negative numbers require special handling.
For example:
-6392
If processed directly, Java's modulus operator produces negative remainders:
-6392 % 10
which gives:
-2
This is not useful because digits are normally treated as positive values.
The simplest solution is to convert the number to its absolute value before extracting digits.
Java Program
public class SmallestLargestNegative {
public static void main(String[] args) {
int num = -6392;
num = Math.abs(num);
int largest = Integer.MIN_VALUE;
int smallest = Integer.MAX_VALUE;
while (num != 0) {
int digit = num % 10;
largest = Math.max(largest, digit);
smallest = Math.min(smallest, digit);
num = num / 10;
}
System.out.println("Largest digit: " + largest);
System.out.println("Smallest digit: " + smallest);
}
}
Output
Largest digit: 9
Smallest digit: 2
Why Use Math.abs()?
The sign (-) is not considered a digit.
By converting:
-6392
to:
6392
the program correctly analyzes only the digits of the number.
This same technique is used in many digit-based algorithms, including:
- Sum of digits
- Reverse a number
- Armstrong number
- Neon number
- Palindrome number
Time Complexity
- Time Complexity: O(d)
- Space Complexity: O(1)
Extension: Finding the Second Largest Digit
A common interview follow-up is:
"Can you also find the second largest digit?"
This problem is slightly more challenging because we must keep track of two values instead of one.
Java Program
public class SecondLargestDigit {
public static void main(String[] args) {
int num = 6392;
int largest = Integer.MIN_VALUE;
int secondLargest = Integer.MIN_VALUE;
while (num != 0) {
int digit = num % 10;
if (digit > largest) {
secondLargest = largest;
largest = digit;
} else if (digit > secondLargest && digit != largest) {
secondLargest = digit;
}
num = num / 10;
}
System.out.println("Largest digit: " + largest);
System.out.println("Second largest digit: " + secondLargest);
}
}
Output
Largest digit: 9
Second largest digit: 6
How It Works
Suppose the digits are:
6
3
9
2
Initially:
largest = Integer.MIN_VALUE
secondLargest = Integer.MIN_VALUE
Processing:
6
updates:
largest = 6
Processing:
9
produces:
secondLargest = 6
largest = 9
Processing:
3
does not change either value.
Processing:
2
also leaves the values unchanged.
Final result:
Largest digit = 9
Second largest digit = 6
Why Check digit != largest?
Consider the number:
9954
Without this condition:
digit != largest
the second occurrence of 9 could incorrectly become the second largest value.
The comparison ensures that the second largest digit is distinct from the largest digit.
This is one of the most common mistakes in interview solutions.
Time Complexity
- Time Complexity: O(d)
- Space Complexity: O(1)
How Java Handles This Internally (Memory Concept)
Methods 1, 2, and 4
The variables:
numdigitlargestsmallest
are primitive int values stored in the JVM stack.
Each loop iteration simply updates these variables.
No heap memory is allocated.
Even:
Math.max()
Math.min()
perform simple primitive comparisons internally and do not create new objects.
Method 3
The recursive implementation behaves differently.
The variables:
largest
smallest
are declared as static.
They belong to the class rather than to individual function calls.
Every recursive call updates the same shared variables.
Meanwhile, each recursive call creates its own stack frame containing:
num
After the base case is reached, the stack frames are removed one by one.
Integer Constants
The values:
Integer.MIN_VALUE
Integer.MAX_VALUE
are predefined constants provided by Java.
They represent the smallest and largest values an int can store:
Integer.MIN_VALUE = -2,147,483,648
Integer.MAX_VALUE = 2,147,483,647
Using these constants guarantees correct initialization for running comparisons.
Real-Life Analogy: Finding the Tallest and Shortest Person
Imagine you're walking through a line of people.
As you meet each person:
- If they're taller than everyone you've seen so far, they become the new tallest.
- If they're shorter than everyone you've seen so far, they become the new shortest.
You never need to compare everyone repeatedly.
You simply update your current tallest and shortest records as you move through the line.
Finding the largest and smallest digit works in exactly the same way.
Each digit is examined once, and the running maximum and minimum values are updated whenever a better candidate is found.
Comparison of All Methods
| Method | Readability | Handles Negative Numbers Automatically? | Time Complexity | Space Complexity | Best Used When |
|---|---|---|---|---|---|
| Manual Comparison | Very clear and explicit | ❌ No | O(d) | O(1) | Learning the comparison logic and interviews |
Math.max() / Math.min() |
Concise and readable | ❌ No | O(d) | O(1) | Production code and cleaner implementations |
| Recursion | Good for demonstrating recursion | ❌ No | O(d) | O(d) | Practicing recursive programming |
| Second Largest Extension | Moderate complexity | ❌ No | O(d) | O(1) | Interview follow-up questions |
Note: Here, d represents the number of digits in the input number.
Best Practices
-
Initialize the tracking variables correctly:
int largest = Integer.MIN_VALUE; int smallest = Integer.MAX_VALUE;This guarantees that the first digit processed will always update both values correctly.
- Prefer
Math.max()andMath.min()when writing production code because they make the comparison logic shorter and easier to read. -
If negative numbers are possible, convert the input to its absolute value before extracting digits:
num = Math.abs(num); - When finding the second largest digit, ensure that duplicate occurrences of the largest digit are not mistakenly treated as the second largest value.
- If this logic is needed repeatedly throughout a larger application, encapsulate it inside a reusable method rather than writing it directly inside
main(). - Test your solution using different types of inputs, including:
- Single-digit numbers
- Numbers containing repeated digits
- Numbers containing zero
- Negative numbers
Common Mistakes Beginners Make
1. Incorrectly Initializing the Tracking Variables
Some beginners write:
int largest = 0;
instead of:
int largest = Integer.MIN_VALUE;
Although digits range only from 0 to 9, using Integer.MIN_VALUE is a better programming practice because it generalizes correctly to other maximum-finding problems.
2. Forgetting to Handle Negative Numbers
Processing a negative number directly may extract negative remainders.
Always write:
num = Math.abs(num);
before processing the digits.
3. Incorrectly Handling Duplicate Digits
Suppose the input is:
9954
The largest digit is:
9
The second largest distinct digit should be:
5
Not:
9
This is why the condition:
digit != largest
is necessary.
4. Using >= Instead of >
Writing:
if (digit >= largest)
instead of:
if (digit > largest)
can change the behavior when duplicate digits are encountered.
Always think carefully about whether duplicates should update the tracking variables.
5. Not Testing Edge Cases
Many solutions work correctly for:
6392
but fail for inputs such as:
5555
or
1000
Always test:
- Repeated digits
- Single-digit numbers
- Numbers containing zeros
- Negative numbers
Expert Tips for Interviews
A strong interview answer might sound like this:
"To find the smallest and largest digit, I repeatedly extract digits using modulus and division while maintaining two running variables initialized to
Integer.MIN_VALUEandInteger.MAX_VALUE. After extracting each digit, I update the running maximum and minimum using either manual comparisons orMath.max()andMath.min(). If asked to find the second largest digit, I maintain an additional variable and carefully handle duplicate digits so that repeated occurrences of the largest value are not incorrectly treated as the second largest."
Mentioning duplicate-digit handling without being prompted demonstrates attention to edge cases, which interviewers often appreciate.
Pros and Cons
Manual Comparison
Pros
- ✅ Easy to understand
- ✅ Shows the comparison logic explicitly
- ✅ Good for beginners and interviews
Cons
- ❌ Slightly more verbose
- ❌ Requires multiple
ifstatements
Using Math.max() and Math.min()
Pros
- ✅ Cleaner code
- ✅ Easier to read
- ✅ Preferred in production code
Cons
- ❌ Slightly less explicit for beginners learning comparison logic
Using Recursion
Pros
- ✅ Demonstrates recursive programming
- ✅ Reuses familiar recursion patterns
- ✅ Useful for loop-free interview questions
Cons
- ❌ Uses additional stack space
- ❌ Relies on static variables in this implementation
- ❌ Less practical than the iterative solution
Second Largest Digit Extension
Pros
- ✅ Common interview follow-up
- ✅ Demonstrates handling multiple running values
- ✅ Encourages careful edge-case handling
Cons
- ❌ Slightly more complex comparison logic
- ❌ Duplicate digits require additional care
Frequently Asked Questions
1. How do I find the largest digit in a number?
Extract each digit using % and /, compare it with the current largest value, and update the result whenever a larger digit is found.
2. How do I find the smallest digit in a number?
Follow the same approach used for the largest digit, but update the tracking variable whenever a smaller digit is encountered.
3. Can I use Math.max() and Math.min()?
Yes.
They provide a cleaner alternative to manual if statements while producing exactly the same result.
4. How do I handle negative numbers?
Convert the number to its absolute value first:
num = Math.abs(num);
Then process its digits normally.
5. How do I find the second largest digit?
Maintain two variables:
largestsecondLargest
Whenever a new maximum is found, move the previous largest value into secondLargest.
Also ensure duplicate largest digits are ignored.
6. Why use Integer.MIN_VALUE instead of 0?
Integer.MIN_VALUE guarantees that the first digit always updates the largest value correctly.
It is also a better general-purpose technique for maximum-finding algorithms.
7. What is the time complexity?
Each digit is processed exactly once.
- Time Complexity: O(d)
where d is the number of digits.
8. Can this problem be solved using recursion?
Yes.
The recursive solution processes one digit per recursive call while updating the running smallest and largest values.
9. What happens if the input contains only one digit?
That single digit is both:
- The largest digit
- The smallest digit
For example:
7
Largest = 7
Smallest = 7
10. Is this a common interview question?
Yes.
It is frequently asked because it tests:
- Digit extraction
- Running comparisons
- Edge-case handling
It is also commonly followed by the "second largest digit" variation.
11. Can I solve this without using a loop?
Yes.
Recursion can replace the loop by processing one digit in each recursive call until the base case is reached.
12. What happens if all digits are the same?
For example:
5555
Then:
- Largest digit = 5
- Smallest digit = 5
For the second largest distinct digit, no valid second value exists.
Your implementation should handle this situation explicitly—for example, by displaying a message such as "Second largest digit not found" or by checking whether secondLargest was ever updated.