LeetCode 258 — Add Digits | Brute Force to O(1) Digital Root Trick Explained in Java
LeetCode 258 — Add Digits | Brute Force to O(1) Digital Root Trick Explained in Java

LeetCode 258 — Add Digits | Brute Force to O(1) Digital Root Trick Explained in Java

Learn how to solve LeetCode 258 Add Digits in Java. We cover the simulation loop approach and the O(1) digital root math trick with full intuition, dry run, and annotated code.

13 views
0
0
Listen to articleAudio version
brillicode ad banner

Introduction

Some problems on LeetCode look too simple to teach you anything meaningful. LeetCode 258 — Add Digits is one of those problems that tricks you with its simplicity. The simulation is beginner-friendly and easy to code in five minutes, but hiding right underneath the surface is a beautiful piece of number theory that lets you solve the entire thing in a single arithmetic expression — no loops, no recursion, pure O(1) math.

Whether you are just starting your DSA journey or preparing for coding interviews, this problem is worth understanding deeply. Not just for the answer, but for the mathematical intuition that produces it. By the end of this article, you will not just know the formula — you will understand exactly why it works, where it comes from, and how to derive it yourself even if you forget it during an interview.

Problem Link

LeetCode 258 — Add Digits https://leetcode.com/problems/add-digits/

Problem Statement

Given an integer num, repeatedly add all its digits until the result has only one digit, and return it.

The follow-up asks: can you solve this in O(1) time without any loop or recursion?

Approach 1 — Simulation (The Intuitive Way)

Intuition

The problem statement itself tells you exactly what to do. Keep summing the digits of the number until you are left with a single digit. You simulate this literally using nested loops.

To extract digits from any integer, two operations do all the work:

num % 10 isolates the rightmost digit. For 38, that gives 8.

num / 10 removes the rightmost digit. For 38, that leaves 3.

You accumulate the digits into a sum, replace num with that sum, and repeat the whole process until num drops below 10.

Dry Run

num = 38

Outer loop iteration 1:

  1. 38 % 10 = 8sum = 8, num = 3
  2. 3 % 10 = 3sum = 11, num = 0
  3. Inner loop ends. num = 11

Outer loop iteration 2:

  1. 11 % 10 = 1sum = 1, num = 1
  2. 1 % 10 = 1sum = 2, num = 0
  3. Inner loop ends. num = 2

num < 10 → outer loop exits → return 2

Code

class Solution {
public int addDigits(int num) {

// If already a single digit, return immediately — no work needed
if (num < 10) return num;

// Keep repeating the digit sum process until num becomes single digit
while (num >= 10) {
int sum = 0;

// Extract each digit from right to left using modulo and division
while (num > 0) {
int dig = num % 10; // isolate the last digit
num = num / 10; // strip the last digit off
sum = sum + dig; // accumulate into running sum
}

// Replace num with the sum of its digits and check again
num = sum;
}

return num;
}
}

Complexity

Time Complexity: O(log n) — Each iteration reduces the number to the sum of its digits, shrinking it dramatically. The number of passes is very small even for large inputs.

Space Complexity: O(1) — Only a handful of integer variables. No extra memory allocated.

This passes all test cases cleanly. But the follow-up challenges you to eliminate the loop entirely. That is where things get genuinely interesting.

Approach 2 — O(1) Digital Root Formula (The Mathematical Way)

Starting With Observation

Before jumping to the formula, let us build the intuition from scratch the way a mathematician would — by looking at small cases and hunting for a pattern.

Let us compute the result for every number from 0 to 27 manually:

num → result
0 → 0
1 → 1
2 → 2
3 → 3
4 → 4
5 → 5
6 → 6
7 → 7
8 → 8
9 → 9
10 → 1 (1+0)
11 → 2 (1+1)
12 → 3 (1+2)
13 → 4 (1+3)
14 → 5 (1+4)
15 → 6 (1+5)
16 → 7 (1+6)
17 → 8 (1+7)
18 → 9 (1+8)
19 → 1 (1+9=10, then 1+0=1)
20 → 2 (2+0)
21 → 3 (2+1)
22 → 4 (2+2)
23 → 5 (2+3)
24 → 6 (2+4)
25 → 7 (2+5)
26 → 8 (2+6)
27 → 9 (2+7)

The pattern is impossible to miss. After 0, the results cycle through 1, 2, 3, 4, 5, 6, 7, 8, 9 and then repeat, endlessly, with a period of exactly 9.

Now the question is — why? Why does the digit sum cycle with period 9? To understand that, we need to talk about what happens to a number modulo 9.

The Core Mathematical Property — Why Digits and Modulo 9 Are Connected

Here is the fundamental theorem that powers this entire solution:

Any positive integer is congruent to the sum of its digits modulo 9.

In plain English: if you take a number, divide it by 9, and note the remainder — that remainder is the same as the remainder you get when you divide the sum of its digits by 9.

Let us prove this properly so it actually makes sense rather than just being a thing you memorize.

Take any two-digit number. You can write it as:

num = 10a + b

Where a is the tens digit and b is the units digit. For example, 38 = 10(3) + 8.

Now notice that 10 = 9 + 1, so:

num = (9 + 1)a + b
= 9a + a + b

When you compute num % 9:

num % 9 = (9a + a + b) % 9
= (9a % 9) + (a + b) % 9
= 0 + (a + b) % 9
= (a + b) % 9

And a + b is exactly the digit sum. So num % 9 = digitSum % 9. They share the same remainder modulo 9.

This same logic extends to three-digit numbers. Write num = 100a + 10b + c. Since 100 = 99 + 1 and 10 = 9 + 1:

num = (99 + 1)a + (9 + 1)b + c
= 99a + 9b + a + b + c

When you take % 9, the 99a and 9b parts vanish because they are divisible by 9, and you are left with (a + b + c) % 9 — which is again just the digit sum modulo 9.

This pattern holds for numbers of any length. Every power of 10 is just 1 more than a multiple of 9 — 10 = 9+1, 100 = 99+1, 1000 = 999+1 — so all the place-value multipliers disappear modulo 9, leaving only the digit sum behind.

This is the reason the digit sum process produces the same final result as the original number modulo 9. The digit sum operation preserves the residue modulo 9 at every step.

Why the Cycle Has Period 9

Now that we know num ≡ digitSum (mod 9), the cycling pattern makes total sense.

Every time you apply the digit sum operation, the result changes but the residue modulo 9 stays the same. You keep applying it until you hit a single digit. The single-digit numbers are 0 through 9. Among those, the residue modulo 9 of each single digit is just the digit itself — except 9, whose residue is 0.

So the final single digit you land on is determined entirely by what num % 9 is:

num % 9 == 0 → result is 9 (for any positive num)
num % 9 == 1 → result is 1
num % 9 == 2 → result is 2
...
num % 9 == 8 → result is 8

The only exception is num = 0 itself, which is a genuine zero, not a nine.

Translating This Into a Formula

If we tried to write this directly as num % 9, there is one problem: multiples of 9 like 9, 18, 27 give a remainder of 0, but the correct answer for all of them is 9, not 0.

We need a formula that maps every positive integer to a value in 1..9 cyclically, rather than 0..8.

The standard trick for shifting a zero-indexed cycle to a one-indexed cycle is to subtract 1 before taking the modulo and add 1 after:

result = 1 + (num - 1) % 9

Let us verify this on a few cases:

num = 9: 1 + (9-1) % 9 = 1 + 8 % 9 = 1 + 8 = 9

num = 18: 1 + (18-1) % 9 = 1 + 17 % 9 = 1 + 8 = 9

num = 1: 1 + (1-1) % 9 = 1 + 0 = 1

num = 10: 1 + (10-1) % 9 = 1 + 9 % 9 = 1 + 0 = 1

num = 38: 1 + (38-1) % 9 = 1 + 37 % 9 = 1 + 1 = 2

The only number this formula does not cover is num = 0, which is a special case handled separately since 0 has no digit sum cycle — it simply returns 0.

Connecting It Back to the Observation

Now look at the table we built earlier through the lens of this formula. Numbers 1 through 9 map to themselves. Then 10 gives 1 + 0 = 1, same as 1. Numbers 10 through 18 are just 1 through 9 offset by 9. Then 19 wraps back to 1. The cycle length of 9 follows directly from the modulo-9 arithmetic. It is not a coincidence at all — it is the inevitable consequence of how place-value and modular arithmetic interact.

Code

class Solution {
public int addDigits(int num) {

// Special case: 0 is not part of the 1-9 cycle, it simply returns 0
if (num == 0) return 0;

// Digital root formula derived from the congruence property modulo 9.
// (num - 1) % 9 maps the range to 0..8 instead of the raw 0..8 cycle
// that would make multiples of 9 return 0 incorrectly.
// Adding 1 at the end shifts it back to the correct 1..9 range.
return 1 + (num - 1) % 9;
}
}

Complexity

Time Complexity: O(1) — A fixed number of arithmetic operations regardless of the size of num.

Space Complexity: O(1) — No variables, no data structures, nothing allocated.

Approach Comparison

ApproachTimeSpaceLoop / Recursion
SimulationO(log n)O(1)Yes
Digital Root FormulaO(1)O(1)No

Both approaches are entirely correct and both pass all test cases. The simulation is more readable and immediately obvious to anyone reading the code. The digital root formula is what an interviewer is hoping you know when they ask the follow-up — and more importantly, if you understand the modulo-9 proof above, you can derive it on the spot rather than hoping you remembered it.

Key Takeaways

The most important thing this problem teaches you is not the formula itself. It is the habit of asking a deeper question when you see a repeated process: is there a closed-form mathematical pattern hiding inside this repetition?

The digit sum operation looks like pure computation at first glance. But underneath it is modular arithmetic, and modular arithmetic has structure that can often be collapsed into a direct formula. That same insight — that repeated digit operations connect to modulo 9 — shows up in divisibility rules you learned in school. A number is divisible by 9 if and only if its digit sum is divisible by 9. A number is divisible by 3 if and only if its digit sum is divisible by 3. Both of those rules are the exact same theorem we used to derive the digital root formula here.

Once you internalize this connection between digit sums and modulo 9, you will recognize it surfacing in other problems across number theory, checksum algorithms, and competitive programming. The formula is a one-liner. The understanding behind it is something you carry with you permanently.

Ai Assistant Kas