Working with digits

Take a number apart with % and /, then count, reverse and compare its digits.

Pattern: Maths20 min read
Quick recall3 questions
  1. 01A loop divides n by 2 until it reaches 1. What is its Big O?

    O(log n). Each pass halves the work, so 1,000,000 needs only about 20 passes.

  2. 02Before you code, which questions do you ask about the input?

    Its range, an empty input, duplicates, negative values, and what to return when there is no answer.

  3. 03Why read the value range in the limits, not only n?

    The values tell you when a number gets too big. JavaScript numbers stay exact only up to about 9 × 10¹⁵.

On paper, 121 is a row of three digits. To your code, it is one value. You cannot index into it like an array.

This lesson gives you one small loop that takes a number apart, digit by digit. Count digits, reverse a number, check a palindrome: all of them use that same loop.

The one move: peel the last digit

Two operations do all the work:

  • n % 10 gives the last digit. The after dividing by 10 is always the units digit.
  • n / 10, with the decimals thrown away, drops the last digit. Each language writes that differently:
LanguageDrop the last digitWhy
Javan / 10int division drops the decimals: 7 / 2 is 3
Pythonn // 10/ gives a float (3.5); // rounds down
TypeScriptMath.floor(n / 10)/ gives decimals, so round down

Repeat both until nothing is left:

Each pass reads one digit from the right, then drops it.

The digits come out in reverse order: 9, 8, 7, 7. Keep that in mind. It is the reason reversing a number is easy.

void printDigits(int n) {
    while (n > 0) {
        int digit = n % 10; // the last digit
        System.out.println(digit);
        n = n / 10; // drop it
    }
}

The loop runs only while n > 0, so handle the sign first. The languages disagree on negative numbers:

  • -7 % 10 is -7 in Java and TypeScript, but 3 in Python.
  • -7 / 10 is 0 in Java. -7 // 10 is -1 in Python, and Math.floor(-7 / 10) is -1 in TypeScript.

Make the number positive, peel it, then put the sign back.

What it costs

Each pass removes one digit. So the loop runs once per digit.

nDigitsPasses
911
5,00044
2,147,483,6471010

A number n has about log₁₀ n digits, so the loop is O(log n). It is the halving loop from Time and space complexity, cutting by 10 each time instead of 2.

Read the problem

Problem: Palindrome Number
it asks
Return true when the integer x reads the same from left to right and from right to left.
example 1
in x = 121 out true

Read backwards, it is still 121.

example 2
in x = -121 out false

Read backwards, it is 121-.

example 3
in x = 10 out false

Read backwards, it is 01.

limits
  • −2³¹ ≤ x ≤ 2³¹ − 1
  • follow-up: no strings
Which pattern? Decide first, then open.

“reads the same from left to right and from right to left”a palindrome: reverse it and compare

“integer, without converting it to a string”peel the digits with % 10 and / 10

pattern: Maths

Ask these before you code:

  • Negative numbers? The minus sign sits only at the front. So every negative number is false.
  • Ends in 0? 10 read backwards is "01". Only 0 itself is a palindrome that ends in 0.
  • One digit? Always true.
  • How big? At most 10 digits. Speed is not the problem here. The follow-up is: solve it without a string.

The input is one number, not an array. So the cost depends on its digit count, not on a length n.

Brute force: turn it into a string

The first idea: make a string, reverse it, compare.

Three steps, and a second copy of the digits in memory.
boolean isPalindrome(int x) {
    String s = String.valueOf(x);
    return s.equals(new StringBuilder(s).reverse().toString());
}
  • The text of -121 is "-121", and its reverse is "121-". So negatives return false with no extra check.
  • Time: one pass to build the string, one to reverse it, one to compare. O(d) for d digits.
  • Space: two strings of d characters, so O(d).

It is correct and fast. But the follow-up says no strings, and the interviewer wants to see you work with the number itself.

The key insight

You can build the reverse with arithmetic. The peel loop already hands you the digits from right to left. Each new digit goes on the end of rev:

× 10 opens an empty slot on the right. + digit fills it.

So one line does it: rev = rev * 10 + digit.

One trap: the loop eats x until it is 0. Save a copy first, so you have something to compare with at the end.

Optimal: reverse with maths

  1. Return false for a negative number.
  2. Save original = x. Start rev at 0.
  3. While x > 0: peel the last digit, push it onto rev, drop it from x.
  4. Return whether rev equals original.

Here it is on 1221. The pointer marks the digit each pass reads.

reverse 1221 with % and /passes 0
1
0
2
1
2
2
1
3
rev{0}

1/6Start with rev = 0. Save a copy: original = 1221.

Four passes for four digits. rev grows by one digit per pass.
boolean isPalindrome(int x) {
    if (x < 0) return false;
    int original = x;
    long rev = 0; // long: a reversed int can pass the int limit
    while (x > 0) {
        int digit = x % 10;
        rev = rev * 10 + digit; // push the digit onto the end of rev
        x = x / 10; // drop it from x
    }
    return rev == original;
}
  • Time: one pass per digit, so O(d), which is O(log x).
  • Space: two numbers, so O(1).
  • 0: the loop never runs, rev stays 0, and 0 equals 0. True.
  • 10: rev ends as 1, which is not 10. False, with no special case.
  • Big values: 2,147,483,647 reversed is 7,463,847,412. That is past the largest Java int, so the Java version keeps rev in a long. A Python int has no limit, and a TypeScript number holds it exactly.

Side by side

ApproachIdeaTimeExtra spaceFits?
Stringreverse the textO(d)O(d)yes, but breaks the follow-up
Mathsrev = rev * 10 + digitO(d)O(1)yes

Here d is the digit count, at most 10.

How to spot this pattern

Signal in the problemWhy it points here
"digits of a number"peel them with % 10
"reverse the number"rev = rev * 10 + digit
"without converting to a string"the interviewer wants the peel loop
a check on each digitone loop, one running answer

The template. Only the middle line changes from problem to problem:

while (n > 0) {
    int digit = n % 10;
    // use digit: count it, add it, compare it
    n = n / 10;
}

The other problems on this lesson's list:

ProblemWhat changes in the loopWatch out
Count all Digitsadd 1 to count0 has one digit, but the loop never runs
Count odd digitsadd 1 when digit % 2 == 10 has no odd digits
Reverse a numberrev = rev * 10 + digit120 reverses to 21. In Java, check for int overflow (LeetCode "Reverse Integer")
Largest digitbest = max(best, digit)start best at 0
Armstrong numberadd digit to the power kcount the k digits first, then compare with a copy

An uses the loop twice: once to count the k digits, once to add each digit to the power k. 153 is 1 + 125 + 27, so it is one.

Factorial is the odd one out. It is a plain loop that multiplies 1 × 2 × … × n, so O(n).

Watch the size. Factorials grow fast:

  • Java: 12! is the largest that fits an int, and 20! the largest that fits a long.
  • Python: an int has no limit, so any factorial is exact.
  • TypeScript: 18! is the largest below Number.MAX_SAFE_INTEGER. Past that, use BigInt.
take U forwardYouTube
Basic Maths for DSA: Strivers A2Z DSA Course
Remember4 points
  1. 01

    n % 10 reads the last digit, and integer division by 10 drops it. One loop of these two takes any number apart.

  2. 02

    The loop runs once per digit, so it is O(log n): 10 passes for a 10-digit number.

  3. 03

    Build a reverse with rev = rev * 10 + digit, and save a copy of the number before the loop eats it.

  4. 04

    Check the edges: 0, one digit, negatives, trailing zeros, and results past your language's integer limit.

Read more

Next: divisors, primes and GCD, where one loop stops at the square root.

Practice

Solve these on the sheet after the lesson. Try each one for 20 minutes before you open its solution.

Striver's A2Z sheet0/8 solved
Open the sheet