Special Number Problems
Solve one Java logic problem at a time, then flip for the complete explanation and program.
Solve one Java logic problem at a time, then flip for the complete explanation and program.
Java Logic Development · Chapter 03 Companion Article
Fifteen classic number-property checks — palindrome, Armstrong, strong, perfect, automorphic, Harshad, neon, spy, duck, sunny, disarium, happy, magic, Peterson, and Kaprekar numbers — each combining digit extraction, arithmetic, loops, and helper methods to test a specific mathematical property.
Special number problems test how well you can combine digit extraction, arithmetic operations, loops, conditions, mathematical properties, and helper methods. These problems are common in beginner-to-intermediate Java coding practice because the same core techniques later appear in array, string, recursion, and algorithm problems.
Most digit-based checks repeatedly use:
number % 10 to extract the last digitnumber / 10 to remove the last digit| Number Type | Main Condition | Example |
|---|---|---|
| Palindrome | Reverse equals original | 121 |
| Armstrong | Sum of powered digits equals number | 153 |
| Strong | Sum of digit factorials equals number | 145 |
| Perfect | Sum of proper divisors equals number | 28 |
| Automorphic | Square ends with original number | 76 |
| Harshad | Number divisible by digit sum | 18 |
| Neon | Sum of digits of square equals number | 9 |
| Spy | Digit sum equals digit product | 1124 |
| Duck | Contains at least one zero after number starts | 1023 |
| Sunny | Number + 1 is a perfect square | 8 |
| Disarium | Positional digit powers sum to number | 135 |
| Happy | Repeated sum of squared digits reaches 1 | 19 |
| Magic | Repeated digit sum becomes 1 | 1729 |
| Peterson | Sum of digit factorials equals number | 145 |
| Kaprekar | Parts of square add to original | 45 |
A palindrome number reads the same from left to right and right to left. Examples: 121 → Palindrome, 1331 → Palindrome, 7 → Palindrome, 123 → Not palindrome. The usual numerical solution reverses the number and compares the reversed value with the original.
For 121: 121 % 10 = 1, 12 % 10 = 2, 1 % 10 = 1. Build the reverse using reverse = reverse * 10 + digit. The multiplication by 10 shifts the existing digits one position to the left.
Preserve the original value before changing the working copy of the number.
public class PalindromeNumber {
static boolean isPalindrome(int number) {
if (number < 0) {
return false;
}
int original = number;
long reverse = 0;
while (number > 0) {
int digit = number % 10;
reverse = reverse * 10 + digit;
number /= 10;
}
return reverse == original;
}
public static void main(String[] args) {
int number = 12321;
System.out.println(number + " is palindrome: " + isPalindrome(number));
}
}
12321 is palindrome: true
For 12321:
| Current Number | Digit | Reverse |
|---|---|---|
| 12321 | 1 | 1 |
| 1232 | 2 | 12 |
| 123 | 3 | 123 |
| 12 | 2 | 1232 |
| 1 | 1 | 12321 |
Since 12321 equals its reverse, it is a palindrome.
O(d)O(1)Here d is the number of digits.
Changing the original number directly and then trying to compare it with the reverse.
An Armstrong number equals the sum of each digit raised to the power of the total number of digits. For 153: 1³ + 5³ + 3³ = 1 + 125 + 27 = 153. Another example: 9474 has four digits: 9⁴ + 4⁴ + 7⁴ + 4⁴ = 9474.
The algorithm requires two operations: count the number of digits, then add each digit raised to that count. This makes the solution work for Armstrong numbers having any number of digits instead of only three-digit numbers.
Do not hard-code cube calculations unless the requirement specifically says three-digit Armstrong numbers.
public class ArmstrongNumber {
static int countDigits(int number) {
if (number == 0) {
return 1;
}
int count = 0;
while (number > 0) {
count++;
number /= 10;
}
return count;
}
static long power(int base, int exponent) {
long result = 1;
for (int i = 0; i < exponent; i++) {
result *= base;
}
return result;
}
static boolean isArmstrong(int number) {
if (number < 0) {
return false;
}
int digits = countDigits(number);
int temp = number;
long sum = 0;
do {
int digit = temp % 10;
sum += power(digit, digits);
temp /= 10;
} while (temp > 0);
return sum == number;
}
public static void main(String[] args) {
int number = 153;
System.out.println(number + " is Armstrong: " + isArmstrong(number));
}
}
153 is Armstrong: true
For 153:
| Digit | Calculation | Running Sum |
|---|---|---|
| 3 | 3³ = 27 | 27 |
| 5 | 5³ = 125 | 152 |
| 1 | 1³ = 1 | 153 |
Final sum = original number.
If d is the number of digits:
O(d)O(d²)O(1)Since decimal integers have a small number of digits, this remains inexpensive in normal interview programs.
A generalized Armstrong solution is stronger than a solution that always calculates digit × digit × digit.
A Strong number equals the sum of factorials of its digits. For 145: 1! + 4! + 5! = 1 + 24 + 120 = 145. Remember: 0! = 1.
Extract every digit, calculate its factorial, and accumulate those factorial values.
Factorial belongs to each individual digit, not to the complete number.
public class StrongNumber {
static int factorial(int number) {
int result = 1;
for (int i = 2; i <= number; i++) {
result *= i;
}
return result;
}
static boolean isStrong(int number) {
if (number <= 0) {
return false;
}
int original = number;
int sum = 0;
while (number > 0) {
int digit = number % 10;
sum += factorial(digit);
number /= 10;
}
return sum == original;
}
public static void main(String[] args) {
int number = 145;
System.out.println(number + " is Strong: " + isStrong(number));
}
}
145 is Strong: true
| Digit | Factorial | Sum |
|---|---|---|
| 5 | 120 | 120 |
| 4 | 24 | 144 |
| 1 | 1 | 145 |
The sum equals 145.
A decimal digit is always between 0 and 9, so factorial calculation performs at most nine multiplications per digit.
O(d)O(1)A positive integer is perfect when the sum of its positive divisors excluding the number itself equals the number. For 28, divisors excluding 28 are 1, 2, 4, 7, 14, and 1 + 2 + 4 + 7 + 14 = 28. Other examples include 6, 28, 496, and 8128.
A basic solution checks every value from 1 to n - 1. A better solution uses divisor pairs — if 2 divides 28, then 14 is automatically another divisor. This allows checking only up to the square root of the number.
When a divisor i is found, also consider number / i instead of scanning the entire range.
public class PerfectNumber {
static boolean isPerfect(int number) {
if (number <= 1) {
return false;
}
long sum = 1;
for (int i = 2; i <= number / i; i++) {
if (number % i == 0) {
sum += i;
int pair = number / i;
if (pair != i) {
sum += pair;
}
}
}
return sum == number;
}
public static void main(String[] args) {
int number = 28;
System.out.println(number + " is Perfect: " + isPerfect(number));
}
}
28 is Perfect: true
For 28:
Result: perfect number.
O(√n)O(1)When checking a perfect square, the divisor pair may contain the same value twice. The condition pair != i prevents adding it twice.
An Automorphic number is a number whose square ends with the same digits as the original number. Examples: 5² = 25 (25 ends with 5); 76² = 5776 (5776 ends with 76). Therefore, both 5 and 76 are Automorphic numbers.
For a two-digit number, compare the last two digits of its square. For a three-digit number, compare the last three digits. The required divisor is 10 raised to the number of digits. For 76: divisor = 100, 5776 % 100 = 76.
Build a power of 10 matching the number's digit count, then use remainder to extract the ending digits.
public class AutomorphicNumber {
static boolean isAutomorphic(int number) {
if (number < 0) {
return false;
}
long divisor = 10;
int temp = number;
while (temp >= 10) {
divisor *= 10;
temp /= 10;
}
long square = (long) number * number;
return square % divisor == number;
}
public static void main(String[] args) {
int number = 76;
System.out.println(number + " is Automorphic: " + isAutomorphic(number));
}
}
76 is Automorphic: true
For 76:
O(d)O(1)Checking only the last digit works for single-digit numbers but fails for values such as 76 or 376.
A Harshad number is divisible by the sum of its digits. For 18, digit sum 1 + 8 = 9, and 18 % 9 = 0. Therefore, 18 is a Harshad number. Harshad numbers are also called Niven numbers.
Calculate the digit sum and then check divisibility.
The actual property is tested only after the complete digit sum has been calculated.
public class HarshadNumber {
static boolean isHarshad(int number) {
if (number <= 0) {
return false;
}
int temp = number;
int sum = 0;
while (temp > 0) {
sum += temp % 10;
temp /= 10;
}
return number % sum == 0;
}
public static void main(String[] args) {
int number = 18;
System.out.println(number + " is Harshad: " + isHarshad(number));
}
}
18 is Harshad: true
For 18:
Result: Harshad number.
O(d)O(1)Performing division before checking that a valid non-zero digit sum exists. Restricting the program to positive integers avoids the zero-divisor problem.
A Neon number is a number where the sum of the digits of its square equals the original number. For 9: 9² = 81, and 8 + 1 = 9. Therefore, 9 is a Neon number.
The digits being processed belong to the square, not the original number.
Square the number first and apply ordinary digit-sum logic to that result.
public class NeonNumber {
static boolean isNeon(int number) {
if (number < 0) {
return false;
}
long square = (long) number * number;
long temp = square;
long sum = 0;
do {
sum += temp % 10;
temp /= 10;
} while (temp > 0);
return sum == number;
}
public static void main(String[] args) {
int number = 9;
System.out.println(number + " is Neon: " + isNeon(number));
}
}
9 is Neon: true
O(d), where d is the number of digits in the squareO(1)Do not confuse Neon numbers with Armstrong numbers.
A Spy number has the same digit sum and digit product. For 1124: sum 1 + 1 + 2 + 4 = 8, product 1 × 1 × 2 × 4 = 8. Therefore, 1124 is a Spy number.
Maintain two accumulators while processing the digits: sum starts at 0, product starts at 1.
Initialize the product with 1 because multiplication starting from 0 would always remain 0.
public class SpyNumber {
static boolean isSpy(int number) {
if (number <= 0) {
return false;
}
int sum = 0;
int product = 1;
int temp = number;
while (temp > 0) {
int digit = temp % 10;
sum += digit;
product *= digit;
temp /= 10;
}
return sum == product;
}
public static void main(String[] args) {
int number = 1124;
System.out.println(number + " is Spy: " + isSpy(number));
}
}
1124 is Spy: true
| Digit | Sum | Product |
|---|---|---|
| 4 | 4 | 4 |
| 2 | 6 | 8 |
| 1 | 7 | 8 |
| 1 | 8 | 8 |
Sum and product are equal.
O(d)O(1)If the number contains zero, its digit product becomes zero. For a normal positive integer containing other digits, its digit sum remains positive, so such a number will not normally satisfy the Spy condition.
A Duck number is a positive number that contains at least one zero in its decimal representation after the number has started. Examples: 1023 → Duck, 12030 → Duck, 504 → Duck, 1234 → Not Duck. Leading zeros are not considered meaningful digits of an integer — 00123 represents the integer 123.
When the input is already stored as an int, leading zeros no longer exist. Therefore, simply scan its digits and check whether any digit equals zero.
Return immediately after finding the first zero because the remaining digits cannot change the result.
public class DuckNumber {
static boolean isDuck(int number) {
if (number <= 0) {
return false;
}
while (number > 0) {
if (number % 10 == 0) {
return true;
}
number /= 10;
}
return false;
}
public static void main(String[] args) {
int number = 1023;
System.out.println(number + " is Duck: " + isDuck(number));
}
}
1023 is Duck: true
For 1023:
O(d)O(1) when a zero is encountered immediatelyO(1)If input such as "00123" must be processed exactly as entered, use a String because numeric variables automatically discard leading zeros. This distinction is often useful in interview questions involving formatting-sensitive input.
A number is Sunny when adding 1 produces a perfect square. For 8: 8 + 1 = 9, and 9 = 3². Therefore, 8 is a Sunny number. Other examples: 3 (3 + 1 = 4), 15 (15 + 1 = 16), 24 (24 + 1 = 25).
Calculate number + 1 and determine whether its square root is an integer.
The property belongs to number + 1, so do not accidentally test whether the original number itself is a perfect square.
public class SunnyNumber {
static boolean isSunny(int number) {
if (number < 0) {
return false;
}
long value = (long) number + 1;
long root = (long) Math.sqrt(value);
return root * root == value;
}
public static void main(String[] args) {
int number = 8;
System.out.println(number + " is Sunny: " + isSunny(number));
}
}
8 is Sunny: true
For 8:
For fixed-size Java integers:
O(1)O(1)Casting Math.sqrt() to an integer removes the fractional portion. Squaring that integer and comparing it with the original value confirms whether the square root was exact.
A Disarium number equals the sum of its digits raised to powers based on their positions from left to right. For 135: 1¹ + 3² + 5³ = 1 + 9 + 125 = 135. Therefore, 135 is a Disarium number. The first digit uses power 1, the second uses power 2, and so on.
Unlike most digit-processing algorithms, position matters. Processing digits from the right with number % 10 requires additional handling because the first extracted digit is actually the last digit. A String representation provides a simple way to process digits directly from left to right.
Use the digit's left-to-right position as the exponent, not the digit count for every digit.
public class DisariumNumber {
static long power(int base, int exponent) {
long result = 1;
for (int i = 0; i < exponent; i++) {
result *= base;
}
return result;
}
static boolean isDisarium(int number) {
if (number < 0) {
return false;
}
String value = String.valueOf(number);
long sum = 0;
for (int i = 0; i < value.length(); i++) {
int digit = value.charAt(i) - '0';
sum += power(digit, i + 1);
}
return sum == number;
}
public static void main(String[] args) {
int number = 135;
System.out.println(number + " is Disarium: " + isDisarium(number));
}
}
135 is Disarium: true
| Position | Digit | Calculation | Sum |
|---|---|---|---|
| 1 | 1 | 1¹ = 1 | 1 |
| 2 | 3 | 3² = 9 | 10 |
| 3 | 5 | 5³ = 125 | 135 |
Final sum equals 135.
With manual exponent calculation:
O(d²)O(d) because the String representation contains all digitsArmstrong and Disarium numbers both use powers, but their exponent rules are different. Armstrong: every digit uses the total digit count. Disarium: every digit uses its position. For 135, the powers are 1, 2 and 3.
A Happy number eventually reaches 1 when repeatedly replaced by the sum of the squares of its digits. For 19: 1² + 9² = 82, 8² + 2² = 68, 6² + 8² = 100, 1² + 0² + 0² = 1. Therefore, 19 is a Happy number.
Not every number reaches 1. Some numbers enter a repeating cycle. Without cycle detection, the program could run forever. A HashSet can store previously calculated values — if the same value appears again, a cycle has been detected.
The difficult part is not calculating squared digits; it is preventing an infinite loop for unhappy numbers.
import java.util.HashSet;
import java.util.Set;
public class HappyNumber {
static int sumOfSquares(int number) {
int sum = 0;
while (number > 0) {
int digit = number % 10;
sum += digit * digit;
number /= 10;
}
return sum;
}
static boolean isHappy(int number) {
if (number <= 0) {
return false;
}
Set seen = new HashSet<>();
while (number != 1 && !seen.contains(number)) {
seen.add(number);
number = sumOfSquares(number);
}
return number == 1;
}
public static void main(String[] args) {
int number = 19;
System.out.println(number + " is Happy: " + isHappy(number));
}
}
19 is Happy: true
For 19:
| Current Value | Next Value |
|---|---|
| 19 | 82 |
| 82 | 68 |
| 68 | 100 |
| 100 | 1 |
Since the process reaches 1, 19 is Happy.
Every transformation processes the digits of the current value. For normal Java int values, the sequence quickly falls into a small numerical range. The HashSet solution uses extra space for previously encountered states, plus digit-processing work during each transformation.
Floyd's cycle detection algorithm can detect the repeating sequence using two variables instead of a HashSet. This reduces auxiliary space to O(1) and is a useful follow-up interview optimization.
Writing while (number != 1) without detecting cycles. That can produce an infinite loop for an unhappy number.
In common Java number-programming exercises, a number is considered Magic when repeatedly summing its digits eventually produces 1. For 1729: 1 + 7 + 2 + 9 = 19, 1 + 9 = 10, 1 + 0 = 1. Therefore, 1729 is a Magic number.
Continue calculating digit sums while the current value contains more than one digit. The final single digit determines the result.
One digit-sum operation may not be enough; continue until only one digit remains.
public class MagicNumber {
static int digitSum(int number) {
int sum = 0;
while (number > 0) {
sum += number % 10;
number /= 10;
}
return sum;
}
static boolean isMagic(int number) {
if (number <= 0) {
return false;
}
while (number >= 10) {
number = digitSum(number);
}
return number == 1;
}
public static void main(String[] args) {
int number = 1729;
System.out.println(number + " is Magic: " + isMagic(number));
}
}
1729 is Magic: true
Result: Magic number.
The number of digits decreases rapidly after each digit-sum operation.
O(d) for practical fixed-size integersO(1)Repeated digit summation is related to the digital root of a number. For positive integers, a final digital root of 1 means the number is congruent to 1 modulo 9. The iterative implementation is usually preferred when the interview question is specifically testing digit-processing logic.
"Magic number" has multiple meanings in computer science and mathematics. Always follow the definition given by the interviewer or problem statement.
A Peterson number is commonly defined in programming exercises as a number equal to the sum of the factorials of its digits. For 145: 1! + 4! + 5! = 1 + 24 + 120 = 145. Therefore, 145 is a Peterson number.
Under the commonly used digit-factorial definition, Peterson Number and Strong Number describe the same numerical property. The two names frequently appear as separate tutorial or interview questions even though their checking condition is identical. Instead of pretending they are different algorithms, this version demonstrates a useful optimization: precomputing factorials for digits 0 through 9.
A decimal digit can only be between 0 and 9. Therefore, factorial values can be calculated once: factorial[0] = 1, factorial[1] = 1, factorial[2] = 2, ..., factorial[9] = 362880. Each digit then requires only an array lookup.
Because only ten possible digits exist, avoid recalculating the same factorial values repeatedly.
public class PetersonNumber {
static boolean isPeterson(int number) {
if (number <= 0) {
return false;
}
int[] factorial = new int[10];
factorial[0] = 1;
for (int i = 1; i <= 9; i++) {
factorial[i] = factorial[i - 1] * i;
}
int original = number;
int sum = 0;
while (number > 0) {
int digit = number % 10;
sum += factorial[digit];
number /= 10;
}
return sum == original;
}
public static void main(String[] args) {
int number = 145;
System.out.println(number + " is Peterson: " + isPeterson(number));
}
}
145 is Peterson: true
For 145:
Building the factorial lookup table always requires only ten entries. For d digits:
O(d)O(1), because the array always contains exactly ten elementsIf both Strong and Peterson numbers appear in a question set, recognize that the mathematical condition is normally identical. The useful discussion is about implementation choices rather than inventing a false distinction.
A Kaprekar number is a positive integer whose square can be divided into two parts that add up to the original number. For 45: 45² = 2025. Split according to the number of digits in 45: 20 | 25, and 20 + 25 = 45. Therefore, 45 is a Kaprekar number. Another example: 9² = 81, 8 + 1 = 9, so 9 is also Kaprekar.
If the original number contains d digits, the right section of its square uses d digits. For 45: d = 2, divisor = 10² = 100, right = 2025 % 100 = 25, left = 2025 / 100 = 20. Then test left + right == number.
Use division and remainder with a power of 10 instead of converting the square into manually selected substrings.
public class KaprekarNumber {
static boolean isKaprekar(int number) {
if (number < 1) {
return false;
}
long divisor = 10;
int temp = number;
while (temp >= 10) {
divisor *= 10;
temp /= 10;
}
long square = (long) number * number;
long right = square % divisor;
long left = square / divisor;
return right > 0 && left + right == number;
}
public static void main(String[] args) {
int number = 45;
System.out.println(number + " is Kaprekar: " + isKaprekar(number));
}
}
45 is Kaprekar: true
For 45:
Result: Kaprekar number.
Without this condition, values whose square ends entirely in zeros may satisfy an unintended split. For example, 100² = 10000. Splitting as 100 | 00 would produce 100 + 0 = 100. Traditional Kaprekar-number checks generally reject such zero-right-part cases.
O(d)O(1)Splitting the square exactly in half based on the square's total length. The correct right-side length is based on the number of digits in the original number.
Several special-number questions look similar because they process digits, but the condition being tested is different.
| Problem | Digits Used From | Operation |
|---|---|---|
| Palindrome | Original number | Reverse |
| Armstrong | Original number | Power by total digit count |
| Strong | Original number | Factorial |
| Peterson | Original number | Factorial |
| Harshad | Original number | Digit sum and divisibility |
| Neon | Square | Digit sum |
| Spy | Original number | Sum and product |
| Disarium | Original number | Power by position |
| Happy | Repeated transformed values | Square of each digit |
| Magic | Repeated transformed values | Digit sum |
| Kaprekar | Square | Split and add |
| Automorphic | Square | Compare ending digits |
Many problems in this chapter use the same fundamental loop:
while (number > 0) {
int digit = number % 10;
// Process digit
number /= 10;
}
Dividing an integer by 10 leaves its last digit as the remainder. Example: 1234 % 10 = 4.
Integer division removes the last digit. Example: 1234 / 10 = 123. The combination allows every decimal digit to be processed without converting the number into a String.
If the algorithm modifies number using division, save the original value before the loop when a final comparison is required. Example: int original = number;
This is required in problems such as:
It is unnecessary when the final condition does not need the original variable after processing or when another unchanged parameter is available.
Even when the input uses int, intermediate arithmetic may exceed the int range. Typical examples include reversing a large integer, calculating a square, calculating powered digits, and accumulating divisor sums.
A safer pattern is:
long square = (long) number * number;
The cast must happen before multiplication. Otherwise, Java performs int multiplication first and overflow may occur before the result is assigned to long.
Incorrect: long square = number * number; — Safer: long square = (long) number * number;
Most problems scan the original digits once. Two important exceptions are:
The number repeatedly changes into the sum of squares of digits. Because an unhappy number can enter a cycle, cycle detection is required.
The number repeatedly changes into the sum of digits. The process stops once a single digit remains.
Recognizing whether a problem requires one pass or repeated transformation is an important logic-development skill.
Most digit problems do not care where a digit appears. For example, digit sum treats these identically: 123 → 1 + 2 + 3 and 321 → 3 + 2 + 1.
Disarium numbers are different because the exponent depends on the digit's position. For 135: 1 uses position 1, 3 uses position 2, 5 uses position 3. When position matters, processing direction must be considered carefully.
Three problems in this chapter depend directly on the square.
Checks whether the square ends with the original number. Example: 76² = 5776.
Adds the digits of the square. Example: 9² = 81 → 8 + 1 = 9.
Splits the square and adds the resulting parts. Example: 45² = 2025 → 20 + 25 = 45.
Although all three start with number × number, their actual validation rules are completely different.
Digit sum appears in several forms.
Uses digit sum as a divisor: number % digitSum == 0
Calculates the digit sum of the square.
Repeatedly calculates digit sums until one digit remains.
Compares digit sum with digit product.
The shared operation is simple, but the surrounding condition determines the actual problem.
Exponent = total number of digits. For 153: 1³ + 5³ + 3³
Exponent = digit position. For 135: 1¹ + 3² + 5³
Exponent is always 2. For 19: 1² + 9²
Understanding this difference prevents mixing three similar-looking algorithms.
Strong and Peterson numbers use the sum of factorials of digits. Example: 145, 1! + 4! + 5! = 145. Because decimal digits are limited to 0 through 9, factorial lookup is an efficient implementation technique. A reusable lookup table can be:
| Digit | Factorial |
|---|---|
| 0 | 1 |
| 1 | 1 |
| 2 | 2 |
| 3 | 6 |
| 4 | 24 |
| 5 | 120 |
| 6 | 720 |
| 7 | 5040 |
| 8 | 40320 |
| 9 | 362880 |
The treatment of zero depends on the mathematical definition:
Always follow the problem's stated definition.
Most special-number definitions are intended for non-negative or positive integers. Unless specifically stated otherwise, negative values should normally return false.
Some properties naturally include many single-digit numbers. For example, every non-negative single-digit number is Armstrong, and every single-digit positive number is palindrome. Several single-digit values may satisfy other special-number properties depending on their mathematical definition. Do not add artificial restrictions unless the question requires them.
Code such as while (number > 0) { number /= 10; } eventually changes number to 0. Save the original value when comparison is required later.
For digit multiplication, correct: int product = 1;. Incorrect: int product = 0; — starting at zero makes every later multiplication remain zero.
Correct: 0! = 1. This matters in Strong and Peterson number calculations.
Expressions involving squares and reversed numbers may exceed int. Use long for intermediate calculations when necessary.
Repeated transformations such as Happy-number processing require a termination strategy for values that never reach 1.
Armstrong uses total digits as the exponent. Disarium uses each digit's position. These are not interchangeable.
Neon uses digits of the square. Armstrong uses digits of the original number. A correct-looking digit loop can still implement the wrong mathematical rule.
| Problem | Basic Approach | Better Observation |
|---|---|---|
| Palindrome | Reverse number | Use long for safe intermediate reverse |
| Armstrong | Calculate powers | Generalize using digit count |
| Strong | Recalculate factorials | Cache factorial values |
| Perfect | Check 1 to n - 1 | Use divisor pairs up to √n |
| Automorphic | Convert to String | Use modulo with power of 10 |
| Harshad | Digit sum | Already O(d) |
| Neon | Square then sum | Use long for square |
| Spy | Separate loops | Calculate sum and product together |
| Duck | Scan all digits | Return immediately when zero appears |
| Sunny | Test divisors | Use square root |
| Disarium | Reverse digits | Process left-to-right positions directly |
| Happy | Unbounded loop | Detect cycles |
| Magic | Repeated digit sum | Stop when one digit remains |
| Peterson | Recalculate factorial | Use ten-value lookup table |
| Kaprekar | String split | Use division and remainder |
For interview-quality Java code, keep the property check separate from main. Preferred structure:
static boolean isSpecialNumber(int number) {
// Checking logic
}
public static void main(String[] args) {
int number = 123;
System.out.println(isSpecialNumber(number));
}
This design has several advantages:
Avoid placing all logic directly inside main unless the problem specifically requires only a minimal demonstration.
After understanding individual checks, useful variations include:
These variations extend the same fundamental algorithms into range processing, arrays, reusable methods, optimization, and classification problems.
After completing these problems, you should be comfortable with: