Topics › Basics › Know Basic Maths

Check if the Number is Armstrong

Easy TUF ID 366 A2Z

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.

  1. If n < 0 return false.
  2. s = Integer.toString(n), k = s.length().
  3. For every character c of s, add (c - '0')^k to a long sum.
  4. 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.

  1. If n < 0 return false.
  2. k = countDigits(n), sum = 0, x = n.
  3. While x > 0: sum += (x % 10)^k; if sum > n return false; x /= 10.
  4. 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