Facebook Pixel

2843. Count Symmetric Integers

EasyMathEnumeration
Leetcode Link

Problem Description

You need to find how many "symmetric" integers exist within a given range [low, high].

A symmetric integer is defined as follows:

  • The integer must have an even number of digits (2 * n digits total)
  • When you split the number in half, the sum of the first n digits must equal the sum of the last n digits
  • Numbers with an odd number of digits can never be symmetric

For example:

  • 1221 is symmetric because it has 4 digits (even), and the sum of first 2 digits (1+2=3) equals the sum of last 2 digits (2+1=3)
  • 123 cannot be symmetric because it has 3 digits (odd)
  • 1234 is not symmetric because it has 4 digits, but the sum of first 2 digits (1+2=3) doesn't equal the sum of last 2 digits (3+4=7)

The solution works by checking each number in the range [low, high]:

  1. Convert the number to a string to easily access individual digits
  2. Check if the length is odd - if yes, return False immediately
  3. If the length is even, split the string in half
  4. Calculate the sum of digits in the first half and the sum of digits in the second half
  5. Return True if these sums are equal, False otherwise

The function f(x) performs this check for a single number x, and the main solution counts how many numbers in the range satisfy this condition.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The most straightforward way to solve this problem is to check every number in the given range individually. Since we need to count how many numbers satisfy a specific condition, and there's no mathematical pattern that would allow us to calculate the count directly, we need to examine each number.

The key insight is that we can treat the number as a string to easily access and manipulate individual digits. This avoids complex mathematical operations like repeatedly dividing by 10 and using modulo to extract digits.

For each number, we need to:

  1. First filter out numbers with odd digit counts since they can never be symmetric by definition
  2. Split the remaining even-digit numbers exactly in half
  3. Compare the digit sums of both halves

The beauty of this approach is its simplicity - we're directly implementing what the problem asks for without trying to optimize prematurely. Since we're dealing with positive integers and a bounded range, the brute force approach is perfectly acceptable.

Using Python's string slicing makes the implementation clean: s[:n] gives us the first half and s[n:] gives us the second half when n is the midpoint. The sum(map(int, s[:n])) construct elegantly converts each character to an integer and sums them in one expression.

The time complexity is O(m * d) where m is the number of integers in the range and d is the average number of digits, which is reasonable for the constraints typically found in such problems.

Learn more about Math patterns.

Solution Approach

The solution uses an enumeration approach to check every integer in the range [low, high].

The implementation consists of two parts:

  1. Helper Function f(x): This function determines whether a given integer x is symmetric.

    • Convert the integer to a string: s = str(x)
    • Check if the length is odd using bitwise AND: if len(s) & 1. This is equivalent to len(s) % 2 == 1 but slightly more efficient
    • If odd, immediately return False since odd-digit numbers cannot be symmetric
    • Calculate the midpoint: n = len(s) // 2
    • Extract and sum the first half: sum(map(int, s[:n]))
    • Extract and sum the second half: sum(map(int, s[n:]))
    • Compare the two sums and return the result
  2. Main Solution: Count all symmetric integers in the range.

    • Use a generator expression with sum() to count: sum(f(x) for x in range(low, high + 1))
    • This iterates through each number from low to high (inclusive)
    • For each number, f(x) returns True (1) or False (0)
    • The sum() function adds up all the True values, giving us the final count

The algorithm leverages Python's string slicing capabilities:

  • s[:n] gets characters from index 0 to n-1 (first half)
  • s[n:] gets characters from index n to the end (second half)

The map(int, s[:n]) pattern converts each character digit to its integer value, allowing us to sum them directly.

This brute-force approach examines each number exactly once, making it O(m) where m is the size of the range [low, high], with each check taking O(d) time where d is the number of digits in the number.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through finding all symmetric integers in the range [low=1200, high=1230].

Step 1: Check each number from 1200 to 1230

For x = 1200:

  • Convert to string: s = "1200"
  • Length is 4 (even), so continue
  • Calculate midpoint: n = 4 // 2 = 2
  • First half: s[:2] = "12", sum = 1 + 2 = 3
  • Second half: s[2:] = "00", sum = 0 + 0 = 0
  • Since 3 ≠ 0, return False

For x = 1201:

  • Convert to string: s = "1201"
  • Length is 4 (even), so continue
  • First half: "12", sum = 1 + 2 = 3
  • Second half: "01", sum = 0 + 1 = 1
  • Since 3 ≠ 1, return False

For x = 1210:

  • Convert to string: s = "1210"
  • Length is 4 (even), so continue
  • First half: "12", sum = 1 + 2 = 3
  • Second half: "10", sum = 1 + 0 = 1
  • Since 3 ≠ 1, return False

For x = 1212:

  • Convert to string: s = "1212"
  • Length is 4 (even), so continue
  • First half: "12", sum = 1 + 2 = 3
  • Second half: "12", sum = 1 + 2 = 3
  • Since 3 = 3, return True

For x = 1221:

  • Convert to string: s = "1221"
  • Length is 4 (even), so continue
  • First half: "12", sum = 1 + 2 = 3
  • Second half: "21", sum = 2 + 1 = 3
  • Since 3 = 3, return True

For x = 1230:

  • Convert to string: s = "1230"
  • Length is 4 (even), so continue
  • First half: "12", sum = 1 + 2 = 3
  • Second half: "30", sum = 3 + 0 = 3
  • Since 3 = 3, return True

Step 2: Count the symmetric numbers

The symmetric numbers found are: 1212, 1221, and 1230.

Final Answer: 3

The algorithm correctly identifies that 3 numbers in the range [1200, 1230] are symmetric by checking each number's digit sum equality after splitting them in half.

Solution Implementation

1class Solution:
2    def countSymmetricIntegers(self, low: int, high: int) -> int:
3        """
4        Count symmetric integers in the range [low, high].
5        A symmetric integer has an even number of digits where the sum of the 
6        first half equals the sum of the second half.
7      
8        Args:
9            low: Lower bound of the range (inclusive)
10            high: Upper bound of the range (inclusive)
11          
12        Returns:
13            Count of symmetric integers in the given range
14        """
15      
16        def is_symmetric(number: int) -> bool:
17            """
18            Check if a number is symmetric.
19          
20            Args:
21                number: Integer to check
22              
23            Returns:
24                True if the number is symmetric, False otherwise
25            """
26            # Convert number to string to access individual digits
27            num_str = str(number)
28          
29            # Check if the number has odd length (not symmetric by definition)
30            if len(num_str) & 1:  # Using bitwise AND to check odd length
31                return False
32          
33            # Calculate the midpoint to split the number into two halves
34            mid = len(num_str) // 2
35          
36            # Calculate sum of first half and second half digits
37            first_half_sum = sum(map(int, num_str[:mid]))
38            second_half_sum = sum(map(int, num_str[mid:]))
39          
40            # Return True if both halves have equal sum
41            return first_half_sum == second_half_sum
42      
43        # Count all symmetric integers in the range [low, high]
44        symmetric_count = sum(is_symmetric(x) for x in range(low, high + 1))
45      
46        return symmetric_count
47
1class Solution {
2    /**
3     * Counts the number of symmetric integers in the range [low, high].
4     * A symmetric integer has an even number of digits where the sum of the first half
5     * of digits equals the sum of the second half of digits.
6     * 
7     * @param low  The lower bound of the range (inclusive)
8     * @param high The upper bound of the range (inclusive)
9     * @return The count of symmetric integers in the given range
10     */
11    public int countSymmetricIntegers(int low, int high) {
12        int count = 0;
13      
14        // Iterate through all numbers in the range [low, high]
15        for (int number = low; number <= high; number++) {
16            count += checkIfSymmetric(number);
17        }
18      
19        return count;
20    }
21  
22    /**
23     * Checks if a given integer is symmetric.
24     * A number is symmetric if it has an even number of digits and
25     * the sum of its first half digits equals the sum of its second half digits.
26     * 
27     * @param number The integer to check
28     * @return 1 if the number is symmetric, 0 otherwise
29     */
30    private int checkIfSymmetric(int number) {
31        // Convert number to string to easily access individual digits
32        String numberString = String.valueOf(number);
33        int length = numberString.length();
34      
35        // Symmetric numbers must have an even number of digits
36        if (length % 2 == 1) {
37            return 0;
38        }
39      
40        // Calculate the sum of the first half and second half of digits
41        int firstHalfSum = 0;
42        int secondHalfSum = 0;
43        int midPoint = length / 2;
44      
45        // Sum the first half of digits
46        for (int i = 0; i < midPoint; i++) {
47            firstHalfSum += numberString.charAt(i) - '0';
48        }
49      
50        // Sum the second half of digits
51        for (int i = midPoint; i < length; i++) {
52            secondHalfSum += numberString.charAt(i) - '0';
53        }
54      
55        // Return 1 if sums are equal (symmetric), 0 otherwise
56        return firstHalfSum == secondHalfSum ? 1 : 0;
57    }
58}
59
1class Solution {
2public:
3    int countSymmetricIntegers(int low, int high) {
4        int count = 0;
5      
6        // Lambda function to check if a number is symmetric
7        auto isSymmetric = [](int number) -> int {
8            // Convert number to string to access individual digits
9            string numStr = to_string(number);
10            int length = numStr.size();
11          
12            // Symmetric integers must have even number of digits
13            if (length & 1) {  // Check if length is odd
14                return 0;
15            }
16          
17            // Calculate sum of first half and second half digits
18            int firstHalfSum = 0;
19            int secondHalfSum = 0;
20            int midPoint = length / 2;
21          
22            for (int i = 0; i < midPoint; ++i) {
23                // Sum digits in first half
24                firstHalfSum += numStr[i] - '0';
25                // Sum digits in second half
26                secondHalfSum += numStr[midPoint + i] - '0';
27            }
28          
29            // Return 1 if sums are equal (symmetric), 0 otherwise
30            return firstHalfSum == secondHalfSum ? 1 : 0;
31        };
32      
33        // Check each number in the range [low, high]
34        for (int currentNum = low; currentNum <= high; ++currentNum) {
35            count += isSymmetric(currentNum);
36        }
37      
38        return count;
39    }
40};
41
1/**
2 * Counts the number of symmetric integers in the given range [low, high].
3 * A symmetric integer has an even number of digits where the sum of the first half
4 * equals the sum of the second half.
5 * @param low - The lower bound of the range (inclusive)
6 * @param high - The upper bound of the range (inclusive)
7 * @returns The count of symmetric integers in the range
8 */
9function countSymmetricIntegers(low: number, high: number): number {
10    let count: number = 0;
11  
12    /**
13     * Checks if a number is symmetric.
14     * @param num - The number to check
15     * @returns 1 if the number is symmetric, 0 otherwise
16     */
17    const isSymmetric = (num: number): number => {
18        const numStr: string = num.toString();
19        const length: number = numStr.length;
20      
21        // Numbers with odd length cannot be symmetric
22        if (length & 1) {
23            return 0;
24        }
25      
26        let leftHalfSum: number = 0;
27        let rightHalfSum: number = 0;
28        const halfLength: number = length >> 1;
29      
30        // Calculate sum of digits in left and right halves
31        for (let i = 0; i < halfLength; ++i) {
32            leftHalfSum += Number(numStr[i]);
33            rightHalfSum += Number(numStr[halfLength + i]);
34        }
35      
36        // Return 1 if sums are equal (symmetric), 0 otherwise
37        return leftHalfSum === rightHalfSum ? 1 : 0;
38    };
39  
40    // Check each number in the range
41    for (let num = low; num <= high; ++num) {
42        count += isSymmetric(num);
43    }
44  
45    return count;
46}
47

Time and Space Complexity

Time Complexity: O(n × log m)

The algorithm iterates through all integers from low to high, giving us n = high - low + 1 iterations. For each integer x in this range, the function f(x) is called, which:

  • Converts the integer to a string: O(log m) where m is the value of the integer (since the number of digits is proportional to log m)
  • Checks the length and performs string slicing: O(log m)
  • Computes the sum of digits for both halves: O(log m) operations

Therefore, the overall time complexity is O(n × log m) where n is the number of integers in the range [low, high] and m is the maximum value in the range.

Space Complexity: O(log m)

The space complexity is determined by:

  • String conversion of integer x: requires O(log m) space to store the string representation
  • String slicing creates two new strings s[:n] and s[n:]: each requires O(log m) space
  • The map function and intermediate computations use O(log m) space

Since these operations are not nested and the space is reused for each integer in the iteration, the overall space complexity is O(log m) where m is the maximum integer value being processed.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Incorrect Handling of Single-Digit Numbers

A common mistake is forgetting that single-digit numbers (1-9) have an odd number of digits and therefore cannot be symmetric by definition. Some might incorrectly consider them symmetric since there's "nothing to compare."

Wrong approach:

def is_symmetric(number):
    num_str = str(number)
    if len(num_str) == 1:
        return True  # WRONG: Single digits are not symmetric
    # ... rest of the code

Correct approach: The original solution correctly handles this by checking if the length is odd and returning False immediately.

2. Off-by-One Error in Range Iteration

The problem specifies an inclusive range [low, high], but Python's range() function is exclusive of the end value. Forgetting to add 1 to high will miss the last value.

Wrong approach:

symmetric_count = sum(is_symmetric(x) for x in range(low, high))  # Misses 'high'

Correct approach:

symmetric_count = sum(is_symmetric(x) for x in range(low, high + 1))  # Includes 'high'

3. Integer Division vs Float Division

When calculating the midpoint, using float division (/) instead of integer division (//) would cause string slicing errors.

Wrong approach:

mid = len(num_str) / 2  # Returns float, causes TypeError in slicing
first_half = num_str[:mid]  # ERROR: slice indices must be integers

Correct approach:

mid = len(num_str) // 2  # Returns integer for proper slicing

4. Misunderstanding the Symmetry Definition

Some might confuse this problem with palindromes or think symmetry means the digits themselves should be equal rather than their sums.

Wrong interpretation:

def is_symmetric(number):
    num_str = str(number)
    if len(num_str) & 1:
        return False
    mid = len(num_str) // 2
    return num_str[:mid] == num_str[mid:]  # WRONG: Comparing strings, not sums

Correct interpretation: The solution should compare the sum of digits in each half, not the digits themselves or their arrangement.

5. Performance Consideration for Large Ranges

While not incorrect, the brute-force approach can be inefficient for very large ranges. For competitive programming with tight time limits, consider optimizing by:

  • Using digit DP (dynamic programming) approaches for counting symmetric numbers
  • Pre-calculating symmetric numbers for specific digit lengths
  • Using mathematical patterns to skip impossible ranges

Example optimization for specific cases:

def count_symmetric_optimized(low, high):
    # Skip ranges that contain only odd-digit numbers
    if high < 10:  # All single-digit
        return 0
    if low >= 10 and high < 100:  # All two-digit numbers
        # Can calculate directly: numbers where both digits are equal
        return len([x for x in range(low, high + 1) if x // 10 == x % 10])
    # ... continue with regular approach for mixed ranges
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

In a binary min heap, the minimum element can be found in:


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More