Topics › Basics › Know Basic Maths
Check if the Number is Armstrong
LeetCode ↗ Java source ↗ Edit this article ↗
Jump to code:
Problem
You are given a non-negative integer n. Let k be the number of decimal digits of n. n is an Armstrong number (also called a narcissistic number) when the sum of its digits, each raised to the power k, equals n itself. Return true if n is Armstrong and false otherwise.
Constraints: 0 ≤ n ≤ 2^31 - 1, so k ≤ 10.
Example 1
n = 153
answer = true // 3 digits: 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153
Example 2
n = 1634
answer = true // 4 digits: 1^4 + 6^4 + 3^4 + 4^4 = 1 + 1296 + 81 + 256 = 1634
Example 3
n = 123
answer = false // 1^3 + 2^3 + 3^3 = 36, not 123
Every single-digit number is an Armstrong number, since d^1 = d. There are only 89 Armstrong numbers in total in base 10 and just 21 of them fit in a 32-bit int; the largest is 912985153.
Approach 1: Brute force, via a string and Math.pow
Intuition. The definition names three things: the digits, their count and a power. A string gives us the first two directly (toCharArray and length), and Math.pow gives the third. Convert each character to its numeric value with c - '0' and add up the powers.
The sum of ten 9th-or-10th powers can exceed int (9^10 is about 3.5 × 10^9), so the accumulator must be a long.
Algorithm.
- If
n < 0returnfalse. s = Integer.toString(n),k = s.length().- For every character
cofs, add(c - '0')^kto alongsum. - Return
sum == n.
static boolean bruteForce(int n) {
if (n < 0) return false;
String s = Integer.toString(n);
int k = s.length();
long sum = 0;
for (char c : s.toCharArray()) {
sum += (long) Math.pow(c - '0', k);
}
return sum == n;
}
Complexity. Time O(k) with Math.pow treated as constant; k ≤ 10. Space O(k) for the string.
A note on Math.pow: it operates on doubles, and in general floating-point powers of integers are not exact. For bases 0..9 and exponents up to 10 every result is below 2^53 and the standard library returns exactly the right integer, so the cast is safe here. For larger ranges prefer integer arithmetic, which is what the next approach does.
Approach 2: Optimal, integer arithmetic only
Intuition. Replace the string with the standard digit loop. First count the digits (k) by dividing by 10 until the number is gone; then peel the digits again with % 10, raising each to the kth power with a small multiplication loop. Everything stays in integers, nothing is allocated, and there is no floating point to worry about.
Because every term is non-negative, the running sum only ever grows. The moment it exceeds n we can stop: no remaining digit can bring it back down. This early exit is a small optimisation, but it is the kind of reasoning (“is the partial result already hopeless?”) that matters in bigger problems.
Algorithm.
- If
n < 0returnfalse. k = countDigits(n),sum = 0,x = n.- While
x > 0:sum += (x % 10)^k; ifsum > nreturnfalse;x /= 10. - Return
sum == n.
static boolean optimal(int n) {
if (n < 0) return false;
int k = countDigits(n);
long sum = 0;
int x = n;
while (x > 0) {
sum += power(x % 10, k);
if (sum > n) return false; // the sum only grows, so n can no longer be reached
x /= 10;
}
return sum == n;
}
The two helpers are deliberately tiny. countDigits uses a do-while so that 0 is reported as one digit, and power multiplies in a long:
static int countDigits(int n) {
int count = 0;
do {
count++;
n /= 10;
} while (n > 0);
return count;
}
static long power(int base, int exp) {
long result = 1;
for (int i = 0; i < exp; i++) result *= base;
return result;
}
Dry run on n = 153 (k = 3):
| x | digit | digit^3 | sum | sum > 153? |
|---|---|---|---|---|
| 153 | 3 | 27 | 27 | no |
| 15 | 5 | 125 | 152 | no |
| 1 | 1 | 1 | 153 | no |
| 0 | loop ends, 153 == 153, true |
Complexity. Time O(k^2): k digits, each raised to the kth power with k multiplications; with k ≤ 10 this is at most 100 multiplications. Space O(1).
For n = 0 the digit count is 1, the while loop does not run, and 0 == 0 gives true, which is the accepted convention.
Listing all Armstrong numbers
A common follow-up is “print all Armstrong numbers up to N”. Just run the check on every candidate:
static List<Integer> allUpTo(int limit) {
List<Integer> out = new ArrayList<>();
for (int n = 0; n <= limit; n++) {
if (optimal(n)) out.add(n);
}
return out;
}
Up to 100000 this produces 0..9, 153, 370, 371, 407, 1634, 8208, 9474, 54748, 92727, 93084, which the tests assert. The test suite also checks that both approaches agree on every n up to 100000.
Edge cases and pitfalls
- Zero and single digits.
0through9are all Armstrong numbers (d^1 = d). Make sure the digit counter returns1for0; a plainwhile (n > 0)counter would return0and0^0ambiguities follow. - Overflow in the sum. For a 10-digit input,
9^10 = 3486784401alone exceedsInteger.MAX_VALUE. Accumulate in along. ForInteger.MAX_VALUEitself the digit powers sum to1702364300, which is in the tests. - Overflow in the power.
powermust multiply in alongas well;result *= basewith anintresult would wrap for9^10. - Using
kwrongly. The exponent is the digit count of the whole number, not3.153is famous because it is a 3-digit example, but1634uses the 4th power and9474does too. Hard-coding3passes153and fails1634. Math.powprecision. Safe here because all values are exact in double precision, but do not castMath.powresults to integers blindly in problems with larger bases or exponents.- Negative input. Not Armstrong by definition; return
falsebefore any digit extraction so%never sees a negative number. - Early exit correctness. Stopping when
sum > nis only valid because every term is non-negative; the same shortcut would be wrong if digits could contribute negative amounts.
Related problems
- Count all Digits of a Number is the
countDigitshelper on its own, with thelog10alternative. - Reverse a number and Palindrome Number use the same
% 10digit loop. - Pow(x,n) replaces the linear
powerloop with fast exponentiation when exponents get large.