Facebook Pixel

869. Reordered Power of 2

MediumHash TableMathCountingEnumerationSorting
Leetcode Link

Problem Description

You are given an integer n. Your task is to determine whether you can rearrange the digits of n (in any order, including keeping the original order) to form a number that is a power of 2.

The only constraint is that the rearranged number cannot have leading zeros (the first digit cannot be 0).

Return true if it's possible to rearrange the digits to form a power of 2, otherwise return false.

For example:

  • If n = 46, you can rearrange it to 64, which is 2^6, so return true
  • If n = 1, it's already 2^0, so return true
  • If n = 10, no valid rearrangement forms a power of 2, so return false

The solution works by comparing the digit composition (frequency of each digit) of the given number with all powers of 2 within the valid range. The function f(x) counts how many times each digit (0-9) appears in number x and returns this as an array. The algorithm then checks all powers of 2 from 1 to 10^9 to see if any of them have the same digit composition as the input number n. If a match is found, it means we can rearrange n to form that power of 2.

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

Intuition

The key insight is that if we can rearrange the digits of n to form a power of 2, then n and that power of 2 must have exactly the same digits - just in different orders. For example, 46 and 64 both contain one '4' and one '6'.

This means we don't actually need to try all possible permutations of n's digits (which could be factorial time complexity). Instead, we can flip the problem around: check if n has the same digit composition as any power of 2.

Since rearranging digits doesn't change which digits we have or how many of each, we can simply count the frequency of each digit (0-9) in our number n. If these frequencies match exactly with the frequencies of any power of 2, then we know we can rearrange n to form that power of 2.

The bounds are important here. The input n can be at most 10^9, which means any valid rearrangement will also be at most 10^9. Powers of 2 grow exponentially (2^30 is already over 10^9), so we only need to check about 30 powers of 2.

This transforms what could be a complex permutation problem into a simple comparison problem: generate all powers of 2 up to 10^9, and for each one, check if it has the same digit frequency distribution as n. If we find a match, return true. If we check all powers of 2 without finding a match, return false.

Learn more about Math and Sorting patterns.

Solution Approach

The implementation uses a helper function f(x) to capture the digit composition of any number x. This function creates an array cnt of size 10 where cnt[i] represents how many times digit i appears in x.

The function f(x) works by repeatedly extracting the last digit of x using the divmod operation:

  • x, v = divmod(x, 10) simultaneously divides x by 10 (removing the last digit) and gets the remainder v (the last digit)
  • We increment cnt[v] to count this digit
  • This continues until x becomes 0

Once we have this helper function, the main algorithm follows these steps:

  1. Calculate target composition: First, we compute target = f(n), which gives us the digit frequency array for the input number n.

  2. Enumerate powers of 2: We start with i = 1 (which is 2^0) and keep doubling it using the left shift operation i <<= 1 (equivalent to multiplying by 2).

  3. Check each power of 2: For each power of 2, we calculate its digit composition using f(i) and compare it with target. If they match exactly (same frequencies for all digits 0-9), we've found a power of 2 that can be formed by rearranging n's digits.

  4. Boundary condition: We continue checking until i exceeds 10^9, since any rearrangement of n cannot exceed this value.

  5. Return result: If we find a match, return True immediately. If we've checked all powers of 2 up to 10^9 without finding a match, return False.

The time complexity is O(log n * log max_value) where we check about 30 powers of 2, and for each one, we extract its digits (at most 10 digits). The space complexity is O(1) since we only use fixed-size arrays of length 10.

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 the example where n = 46.

Step 1: Calculate the digit composition of n = 46

  • Using function f(46):
    • 46 % 10 = 6, so cnt[6] = 1, then 46 // 10 = 4
    • 4 % 10 = 4, so cnt[4] = 1, then 4 // 10 = 0
    • Result: target = [0,0,0,0,1,0,1,0,0,0] (one '4' and one '6')

Step 2: Check powers of 2

  • Start with i = 1 (2^0):

    • f(1) = [0,1,0,0,0,0,0,0,0,0] (one '1')
    • Doesn't match target ❌
  • i = 2 (2^1):

    • f(2) = [0,0,1,0,0,0,0,0,0,0] (one '2')
    • Doesn't match target ❌
  • i = 4 (2^2):

    • f(4) = [0,0,0,0,1,0,0,0,0,0] (one '4')
    • Doesn't match target ❌
  • Continue through i = 8, 16, 32...

  • i = 64 (2^6):

    • f(64) = [0,0,0,0,1,0,1,0,0,0] (one '4' and one '6')
    • Matches target! ✓

Step 3: Return true

Since we found that 64 has the same digit composition as 46, we know we can rearrange the digits of 46 to form 64, which is a power of 2.

The algorithm efficiently checked only the powers of 2 rather than trying all possible permutations of 46 (which would be 46 and 64 in this case). This demonstrates how the solution transforms a permutation problem into a simple frequency comparison problem.

Solution Implementation

1class Solution:
2    def reorderedPowerOf2(self, n: int) -> bool:
3        """
4        Check if integer n can be reordered to form a power of 2.
5      
6        Args:
7            n: A positive integer to check
8          
9        Returns:
10            True if digits of n can be rearranged to form a power of 2, False otherwise
11        """
12      
13        def get_digit_frequency(number: int) -> list[int]:
14            """
15            Count the frequency of each digit (0-9) in the given number.
16          
17            Args:
18                number: The integer to analyze
19              
20            Returns:
21                A list of 10 integers where index i contains the count of digit i
22            """
23            digit_count = [0] * 10
24          
25            # Extract each digit and count its frequency
26            while number > 0:
27                number, remainder = divmod(number, 10)
28                digit_count[remainder] += 1
29              
30            return digit_count
31      
32        # Get the digit frequency of the input number
33        target_frequency = get_digit_frequency(n)
34      
35        # Check all powers of 2 up to 10^9
36        power_of_two = 1
37        while power_of_two <= 10**9:
38            # Compare digit frequencies
39            if get_digit_frequency(power_of_two) == target_frequency:
40                return True
41          
42            # Move to next power of 2 using left shift
43            power_of_two <<= 1
44          
45        return False
46
1class Solution {
2    /**
3     * Determines if a given integer can be reordered to form a power of 2.
4     * 
5     * @param n The integer to check
6     * @return true if digits of n can be reordered to form a power of 2, false otherwise
7     */
8    public boolean reorderedPowerOf2(int n) {
9        // Get the digit frequency signature of the input number
10        String targetSignature = getDigitFrequencySignature(n);
11      
12        // Check all powers of 2 up to 10^9 (since n <= 10^9)
13        // Each iteration multiplies i by 2 using left shift operation
14        for (int powerOf2 = 1; powerOf2 <= 1_000_000_000; powerOf2 <<= 1) {
15            // Compare digit frequency signatures
16            if (targetSignature.equals(getDigitFrequencySignature(powerOf2))) {
17                return true;
18            }
19        }
20      
21        return false;
22    }
23
24    /**
25     * Creates a unique signature representing the frequency of each digit (0-9) in a number.
26     * The signature is a string where each character position represents the count of that digit.
27     * 
28     * @param number The number to analyze
29     * @return A string signature representing digit frequencies
30     */
31    private String getDigitFrequencySignature(int number) {
32        // Array to store frequency count of each digit (0-9)
33        char[] digitFrequency = new char[10];
34      
35        // Extract each digit and increment its frequency count
36        while (number > 0) {
37            int digit = number % 10;
38            digitFrequency[digit]++;
39            number /= 10;
40        }
41      
42        // Convert frequency array to string for easy comparison
43        return new String(digitFrequency);
44    }
45}
46
1class Solution {
2public:
3    bool reorderedPowerOf2(int n) {
4        // Get the digit frequency signature of the input number
5        string targetSignature = getDigitFrequencySignature(n);
6      
7        // Check all powers of 2 up to 10^9
8        // Starting from 2^0 = 1, multiply by 2 each iteration (left shift by 1)
9        for (int powerOfTwo = 1; powerOfTwo <= 1000000000; powerOfTwo <<= 1) {
10            // If any power of 2 has the same digit frequency signature,
11            // then n can be reordered to form that power of 2
12            if (targetSignature == getDigitFrequencySignature(powerOfTwo)) {
13                return true;
14            }
15        }
16      
17        return false;
18    }
19
20private:
21    // Helper function to create a frequency signature of digits in a number
22    // Returns a string where index i contains the count of digit i (0-9)
23    string getDigitFrequencySignature(int number) {
24        // Array to store frequency of each digit (0-9)
25        char digitCount[10] = {};
26      
27        // Extract each digit and increment its count
28        while (number > 0) {
29            digitCount[number % 10]++;
30            number /= 10;
31        }
32      
33        // Convert the frequency array to a string representation
34        // This creates a unique signature for each digit combination
35        return string(digitCount, digitCount + 10);
36    }
37};
38
1/**
2 * Determines if a number can be reordered to form a power of 2
3 * @param n - The input number to check
4 * @returns true if digits of n can be reordered to form a power of 2, false otherwise
5 */
6function reorderedPowerOf2(n: number): boolean {
7    /**
8     * Counts the frequency of each digit in a number
9     * @param x - The number to analyze
10     * @returns A string representation of digit frequencies (comma-separated)
11     */
12    const getDigitFrequency = (x: number): string => {
13        // Initialize array to count occurrences of each digit (0-9)
14        const digitCount: number[] = Array(10).fill(0);
15      
16        // Count each digit in the number
17        while (x > 0) {
18            // Get the last digit and increment its count
19            digitCount[x % 10]++;
20            // Remove the last digit using bitwise OR for integer division
21            x = (x / 10) | 0;
22        }
23      
24        // Convert digit count array to string for easy comparison
25        return digitCount.join(',');
26    };
27  
28    // Get the digit frequency signature of the input number
29    const targetSignature: string = getDigitFrequency(n);
30  
31    // Check all powers of 2 up to 10^9
32    // Left shift operation (i <<= 1) multiplies by 2 each iteration
33    for (let powerOf2 = 1; powerOf2 <= 1_000_000_000; powerOf2 <<= 1) {
34        // Compare digit frequency signatures
35        if (targetSignature === getDigitFrequency(powerOf2)) {
36            return true;
37        }
38    }
39  
40    // No matching power of 2 found
41    return false;
42}
43

Time and Space Complexity

Time Complexity: O(log^2 M), where M = 10^9 is the upper limit of the input range.

The analysis breaks down as follows:

  • The outer loop iterates through all powers of 2 up to 10^9. Since we're doubling i each time (i <<= 1), we have log₂(10^9) ≈ 30 iterations.
  • For each iteration, we call function f(i) which extracts digits from the number. The f function runs in O(log₁₀(i)) time, as it processes each digit of the number. The maximum value of i is 10^9, so this takes at most O(log₁₀(10^9)) = O(9) = O(log M) time.
  • We also call f(n) once at the beginning, which takes O(log n) = O(log M) time.
  • The comparison f(i) == target takes O(10) = O(1) time since we're comparing two arrays of fixed size 10.

Therefore, the total time complexity is O(log M) + O(log M × log M) = O(log^2 M).

Space Complexity: O(log M)

The space analysis:

  • Function f creates an array cnt of fixed size 10, which is O(1).
  • The target array stores the digit count of n, also using O(1) space.
  • The recursive call stack depth is at most 1 since f is not recursive.
  • However, when considering the representation of numbers themselves and the digit extraction process, we need O(log M) space to represent the largest possible number in the range.

Therefore, the space complexity is O(log M).

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

Common Pitfalls

1. Incorrect Upper Bound for Powers of 2

A common mistake is using the wrong upper bound when checking powers of 2. Some might incorrectly assume the upper bound should be based on the maximum value that can be formed from rearranging the digits of n.

Pitfall Example:

# INCORRECT: Using n's digit count to determine upper bound
max_possible = 10 ** len(str(n)) - 1
power_of_two = 1
while power_of_two <= max_possible:
    # Check power of 2
    power_of_two <<= 1

Why it's wrong: If n = 128, the maximum rearrangement is 821, but we'd miss checking 1024 (2^10) which has the same digits as 1024{0:1, 1:1, 2:1, 4:1}. The digit composition matters, not just the original number's magnitude.

Solution: Always use 10^9 as the upper bound since the problem constraints specify this limit, ensuring all valid powers of 2 are checked regardless of the input's digit count.

2. String-Based Comparison Instead of Frequency Arrays

Some might try to sort the digits as strings and compare them directly:

Pitfall Example:

# INCORRECT: String sorting approach
def reorderedPowerOf2(self, n: int) -> bool:
    sorted_n = sorted(str(n))
    power_of_two = 1
    while power_of_two <= 10**9:
        if sorted(str(power_of_two)) == sorted_n:
            return True
        power_of_two <<= 1
    return False

Why it's problematic: While this works functionally, it's less efficient due to string conversions and sorting operations (O(d log d) for each comparison where d is the number of digits). The frequency array approach is O(d) for both creation and comparison.

3. Off-by-One Error in Power Generation

Starting with the wrong initial power or using incorrect increment logic:

Pitfall Example:

# INCORRECT: Starting from 2 instead of 1
power_of_two = 2  # Misses 2^0 = 1
while power_of_two <= 10**9:
    # Check logic
    power_of_two *= 2

Solution: Always start with power_of_two = 1 (which is 2^0) to ensure all powers are checked.

4. Forgetting Edge Cases

Not handling single-digit inputs properly, especially n = 1, 2, 4, 8:

Pitfall Example:

# INCORRECT: Premature optimization that breaks edge cases
if n < 10:
    # Assuming single digits can't be rearranged
    return n in [1, 2, 4, 8]  # But what about checking if it's already a power of 2?

Solution: The frequency-based approach naturally handles all cases uniformly without special-casing single digits.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Which data structure is used to implement recursion?


Recommended Readings

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

Load More