Talentd
FleetCode
Make and follow sheets.Sign in

Count Evenly Good Integers solution and explanation

Hard6 min read77.8% acceptanceUpdated 9 Oct 2026Premium elsewhere, free here

The problem

You are given two integers l and r.

An integer is called evenly good if it contains an even number of even digits.

Return the number of evenly good integers in the inclusive range [l, r].

Example 1:

Input: l = 18, r = 22

Output: 3

Explanation:

The evenly good integers in the range [18, 22] are:

  • 19, because it contains 0 even digits.
  • 20, because it contains 2 even digits.
  • 22, because it contains 2 even digits.

Thus, the answer is 3.

Example 2:

Input: l = 98, r = 101

Output: 2

Explanation:

The evenly good integers in the range [98, 101] are:

  • 99, because it contains 0 even digits.
  • 100, because it contains 2 even digits.

Thus, the answer is 2.

Example 3:

Input: l = 1, r = 10

Output: 5

Explanation:

The evenly good integers in the range [1, 10] are 1, 3, 5, 7, and 9, because each of them contains 0 even digits. Thus, the answer is 5.

Constraints:

  • 1 <= l <= r <= 1015

Approach overview

Problem Overview: You are given a range of integers and must count how many of them satisfy the evenly good condition defined in the statement. The condition depends on the digits of each number, so you need a way to reason about digits without checking every value one by one when the range is large.

Approach 1: Brute Force Enumeration (O(N * d) time, O(1) space)

Iterate over every integer in the range, extract its digits with repeated division by 10, and test the condition on each one. Each check costs O(d) where d is the number of digits. This is correct and easy to verify, but when the bounds reach 10^18 it cannot finish. Use it to validate your reasoning on small inputs, not as the final answer.

Approach 2: Digit DP with Memoization (O(d * S * 10) time, O(d * S) space)

Process the number digit by digit from the most significant position. Track three things in the state: the current position, a tight flag that says whether the prefix so far equals the upper bound's prefix, and whatever digit-level summary the condition needs (for example, a running count, parity, or a set-like mask). At each position, try every digit from 0 to 9 that respects the tight limit, update the summary, and recurse. Memoize on (position, summary, tight) so each state is computed once. Counting the complete numbers in [0, N] and subtracting the count for [0, L - 1] gives the answer for any range. Prefer this approach whenever the bounds are large and the condition can be summarized in a small state.

Approach 3: Iterative Bottom-Up Digit DP (O(d * S * 10) time, O(S) space per layer)

Convert the recursive memoization into a table filled from the last digit position back to the first. This removes recursion depth concerns and lets you roll the table into two arrays, cutting memory from O(d * S) to O(S). The transitions are identical to Approach 2. Use this version in languages where recursion overhead or stack limits matter, such as C++ or Go under tight constraints.

Recommended for interviews: Start by stating the brute force and its complexity, then explain why it fails on large bounds. Interviewers expect you to reach digit DP and to explain the state definition clearly. The brute force shows you understand the problem. The digit DP with a correctly chosen state shows the skill they are looking for. Practice the broader pattern in dynamic programming and math problems, since digit DP reuses both ideas.

Solution

Thinking

r can be as large as 10^{15}, so checking every integer in [l, r] does not finish in time. The range count equals F(r)-F(l-1), so it is enough to count integers up to one upper bound.

An integer is evenly good exactly when its number of even digits is even, so the digits can be filled from high to low.

When x has d digits, every shorter integer shows up with leading zeros, and those zeros are even digits. On [0, 10^{d-1}-1] the count that includes those zeros equals the count from the ordinary decimal form, and a full d-digit integer has no leading zero, so the two counts agree on [0, x].

The search state is then the position, the even-digit count modulo 2, and whether the prefix is tight. Each digit is chosen from 0 through the current limit, an even digit flips the parity, and a finished number is counted when the parity is even.

Let F(x) be the number of evenly good integers in [0, x]. The answer is F(r)-F(l-1). The decimal form of 0 is the single digit 0, which has an odd number of even digits, so F(0)=0.

Write x as a decimal string s and search from high digits to low digits with memoization. dfs(pos, st, lim) is the number of ways to fill position pos when the even digits placed so far number st modulo 2, and lim says whether the prefix is tight against x.

At the end of the string, return 1 when st=0 and return 0 otherwise. The upper digit up equals s[pos] when the prefix is tight, and equals 9 otherwise. For a digit i from 0 to up, the next parity is (st+1)bmod 2 when i is even and stays st when i is odd. The next position stays tight only when lim is true and i=up.

Among 0 through 9, five digits are even and five are odd, so a free run of digits splits evenly between the two parities. When x has d\ge 2 digits, every integer with fewer digits appears in this search with leading zeros, and those integers are exactly [0, 10^{d-1}-1]. After padding to d digits the leading digit is the even digit 0 and the rest are free, which gives 10^{d-1}/2 strings with an even number of even digits. In the ordinary decimal form there are 5 one-digit evenly good integers, and a length k\ge 2 contributes exactly half of its integers. Summing lengths 1 through d-1 gives

$ 5+sum_{k=2}^{d-1}\frac{9}{2}times 10^{k-1}=\frac{10^{d-1}}{2}.

An integer that already has d digits and does not exceed x has no leading zero, so the two writings match. The search therefore returns F(x).

The time complexity is O(log r) and the space complexity is O(log r)$.

class Solution:
    def countEvenlyGoodIntegers(self, l: int, r: int) -> int:
        @cache
        def dfs(pos: int, st: int, lim: bool) -> int:
            if pos >= len(s):
                return st ^ 1
            up = int(s[pos]) if lim else 9
            return sum(
                dfs(pos + 1, (st + (i & 1 ^ 1)) % 2, lim and i == up)
                for i in range(up + 1)
            )

        s = str(l - 1)
        a = dfs(0, 0, True)
        dfs.cache_clear()
        s = str(r)
        b = dfs(0, 0, True)
        return b - a
class Solution {
    String s;
    long[][][] f;

    public long countEvenlyGoodIntegers(long l, long r) {
        return calc(r) - calc(l - 1);
    }

    private long calc(long x) {
        s = String.valueOf(x);
        f = new long[s.length()][2][2];
        for (long[][] a : f) {
            for (long[] b : a) {
                Arrays.fill(b, -1);
            }
        }
        return dfs(0, 0, true);
    }

    private long dfs(int pos, int st, boolean lim) {
        if (pos >= s.length()) {
            return st ^ 1;
        }
        int k = lim ? 1 : 0;
        if (f[pos][st][k] != -1) {
            return f[pos][st][k];
        }
        int up = lim ? s.charAt(pos) - '0' : 9;
        long res = 0;
        for (int i = 0; i <= up; ++i) {
            res += dfs(pos + 1, (st + (i & 1 ^ 1)) % 2, lim && i == up);
        }
        return f[pos][st][k] = res;
    }
}
class Solution {
    string s;
    long long f[20][2][2];

    long long dfs(int pos, int st, bool lim) {
        if (pos >= s.size()) {
            return st ^ 1;
        }
        if (f[pos][st][lim] != -1) {
            return f[pos][st][lim];
        }
        int up = lim ? s[pos] - '0' : 9;
        long long res = 0;
        for (int i = 0; i <= up; ++i) {
            res += dfs(pos + 1, (st + (i & 1 ^ 1)) % 2, lim && i == up);
        }
        return f[pos][st][lim] = res;
    }

    long long calc(long long x) {
        s = to_string(x);
        memset(f, -1, sizeof(f));
        return dfs(0, 0, true);
    }

public:
    long long countEvenlyGoodIntegers(long long l, long long r) {
        return calc(r) - calc(l - 1);
    }
};
function countEvenlyGoodIntegers(l: number, r: number): number {
    let s: string;
    let f: number[][][];

    const calc = (x: number): number => {
        s = String(x);
        f = Array.from({ length: s.length }, () =>
            Array.from({ length: 2 }, () => Array(2).fill(-1)),
        );

        const dfs = (pos: number, st: number, lim: boolean): number => {
            if (pos >= s.length) {
                return st ^ 1;
            }
            const k = lim ? 1 : 0;
            if (f[pos][st][k] !== -1) {
                return f[pos][st][k];
            }
            const up = lim ? Number(s[pos]) : 9;
            let res = 0;
            for (let i = 0; i <= up; ++i) {
                res += dfs(pos + 1, (st + ((i & 1) ^ 1)) % 2, lim && i === up);
            }
            return (f[pos][st][k] = res);
        };

        return dfs(0, 0, true);
    };

    return calc(r) - calc(l - 1);
}
func countEvenlyGoodIntegers(l int64, r int64) int64 {
	var s string
	var f [20][2][2]int64

	calc := func(x int64) int64 {
		s = strconv.FormatInt(x, 10)
		for i := range f {
			for j := range f[i] {
				for k := range f[i][j] {
					f[i][j][k] = -1
				}
			}
		}

		var dfs func(pos, st int, lim bool) int64
		dfs = func(pos, st int, lim bool) int64 {
			if pos >= len(s) {
				return int64(st ^ 1)
			}
			k := 0
			if lim {
				k = 1
			}
			if f[pos][st][k] != -1 {
				return f[pos][st][k]
			}
			up := 9
			if lim {
				up = int(s[pos] - '0')
			}
			var res int64
			for i := 0; i <= up; i++ {
				res += dfs(pos+1, (st+(i&1^1))%2, lim && i == up)
			}
			f[pos][st][k] = res
			return res
		}

		return dfs(0, 0, true)
	}

	return calc(r) - calc(l-1)
}
Try this approach in the editor

Complexity analysis

ApproachTimeSpaceWhen to Use
Brute Force EnumerationO(N * d)O(1)Small bounds, verifying results
Digit DP (Memoized)O(d * S * 10)O(d * S)General case with large bounds
Digit DP (Bottom-Up)O(d * S * 10)O(S)Memory constrained or no recursion allowed

Frequently asked questions

Count Evenly Good Integers Python solution?

In Python, convert the upper bound to a string to get its digits, then define a recursive function with @lru_cache over (position, summary, tight). Iterate over digits 0 to 9, respect the upper bound when tight is true, and update the summary for each choice. Subtract the count for L - 1 from the count for R to get the range answer.

Is Count Evenly Good Integers easy or hard?

It is rated Hard on FleetCode, with an acceptance rate of about 79.6 percent. The difficulty comes from designing the digit DP state correctly rather than from the code itself. Once the state is clear, the implementation is a standard memoized recursion.

How to solve Count Evenly Good Integers in O(log N)?

Use digit DP. The number of digits is log10(N), so the position dimension is O(log N), and the transitions per state are constant (at most 10 digit choices). The total work is O(log N * S), where S is the size of the summary state. Memoization ensures each (position, summary, tight) combination is computed only once.

What is the best approach for Count Evenly Good Integers?

Digit DP is the best approach. It processes the number digit by digit, tracks a tight-bound flag and a compact summary of the digits seen so far, and memoizes each state. This runs in O(d * S * 10) time, where d is the digit count and S is the number of summary states, which stays fast even for bounds near 10^18.

What data structure is used in Count Evenly Good Integers?

The main structure is a memoization table, usually a multidimensional array indexed by digit position, summary state, and tight flag, or a hash map keyed by those values. Digits are extracted from the bound with integer division and modulo by 10, so no string or list is strictly required.

What is the time complexity of Count Evenly Good Integers?

The optimal digit DP solution runs in O(d * S * 10) time, where d is the number of digits in the bound and S is the number of distinct summary states. The brute force enumeration runs in O(N * d) time, where N is the size of the range, which is too slow for large inputs.

Is Count Evenly Good Integers asked at Google, Amazon, or Meta?

The FleetCode listing tags this problem under General and does not list specific company associations. Digit DP problems appear regularly in interviews at large tech companies, so practicing the pattern is useful regardless of which company you target.

Comments

Now write it yourselfClose this page and solve Count Evenly Good Integers in the editor, without looking.
Practise Count Evenly Good Integers