title: Check if Number is a Sum of Powers of Three slug: check-if-number-is-a-sum-of-powers-of-three difficulty: medium leetcode_id: 1780 leetcode_url: https://leetcode.com/problems/check-if-number-is-a-sum-of-powers-of-three/ categories: - math patterns: - greedy description: | Given an integer `n`, return `true` *if it is possible to represent* `n` *as the sum of distinct powers of three*. Otherwise, return `false`. An integer `y` is a power of three if there exists an integer `x` such that `y == 3^x`. constraints: | - `1 <= n <= 10^7` examples: - input: "n = 12" output: "true" explanation: "12 = 3^1 + 3^2 = 3 + 9" - input: "n = 91" output: "true" explanation: "91 = 3^0 + 3^2 + 3^4 = 1 + 9 + 81" - input: "n = 21" output: "false" explanation: "21 cannot be represented as a sum of distinct powers of three." explanation: intuition: | Think of this problem like converting a number to a different base system, specifically **base 3 (ternary)**. In our familiar decimal system, we use digits 0-9. In binary (base 2), we use 0-1. In ternary (base 3), we use digits 0, 1, and 2. Each position represents a power of 3: the rightmost position is 3^0 = 1, the next is 3^1 = 3, then 3^2 = 9, and so on. Here's the key insight: when we represent `n` in base 3, if all digits are either **0 or 1**, then `n` can be written as a sum of distinct powers of three. Why? Because a digit of 1 in position `i` means we include 3^i in our sum, and a digit of 0 means we don't. Each power of three is used at most once. However, if any digit is **2**, that means we need to use some power of three *twice* in our sum, which violates the "distinct" requirement. For example, 21 in base 3 is `210` (2×9 + 1×3 + 0×1), meaning we'd need to use 3^2 = 9 twice — not allowed! So the problem reduces to: **convert `n` to base 3 and check if all digits are 0 or 1**. approach: | We solve this using **Ternary (Base-3) Digit Checking**: **Step 1: Repeatedly extract the last digit in base 3** - Use `n % 3` to get the rightmost digit in base 3 - If this digit is 2, immediately return `false` - A digit of 2 means we'd need to use that power of 3 twice   **Step 2: Remove the last digit** - Use integer division `n //= 3` to remove the digit we just checked - This shifts all remaining digits one position to the right   **Step 3: Repeat until n becomes 0** - Continue the loop while `n > 0` - If we check all digits without finding a 2, return `true`   This is essentially converting `n` to base 3 and validating each digit as we go, without storing the full representation. common_pitfalls: - title: Trying All Combinations of Powers description: | A brute force approach might try to enumerate all possible subsets of powers of 3 up to `n` and check if any subset sums to `n`. With `n <= 10^7`, we have up to 15 powers of 3 (since 3^15 > 10^7). Checking all 2^15 = 32,768 subsets is technically feasible but unnecessary and much slower than the O(log n) ternary approach. wrong_approach: "Enumerate all subsets of powers of 3" correct_approach: "Check base-3 representation for digit 2" - title: Forgetting Why Digit 2 Fails description: | It's important to understand *why* a digit of 2 means the answer is false. If the base-3 representation has a 2 in position `i`, that means `n` contains `2 × 3^i` as part of its decomposition. Since we can only use each power of 3 at most once (distinct), we cannot represent `2 × 3^i` as a sum of distinct powers. For instance, `2 × 9 = 18` cannot be written as a sum of distinct powers of 3 that equals 18 — we'd need 9 + 9, but that uses 9 twice. wrong_approach: "Not understanding the connection to base-3" correct_approach: "Recognise that ternary digits > 1 require repeated powers" - title: Integer Overflow with Large Powers description: | If you precompute all powers of 3 up to `n`, be careful not to overflow. In Python this isn't an issue, but in languages like C++ or Java, 3^20 exceeds 32-bit integer limits. The iterative modulo approach avoids this entirely since we only work with values up to `n`. wrong_approach: "Precomputing large powers without overflow checks" correct_approach: "Use iterative n % 3 and n // 3 approach" key_takeaways: - "**Base conversion insight**: Many problems involving sums of distinct powers can be solved by examining the number in that base" - "**Ternary representation**: A number is a sum of distinct powers of 3 if and only if its base-3 representation contains only 0s and 1s" - "**Pattern recognition**: This same logic applies to powers of any base — e.g., all positive integers are sums of distinct powers of 2 (binary has only 0s and 1s by definition)" - "**Efficiency through number theory**: Converting a brute force subset problem into a simple digit-checking problem reduces complexity dramatically" time_complexity: "O(log n). We divide `n` by 3 in each iteration, so we process at most log_3(n) digits." space_complexity: "O(1). We only use a single variable to track `n` as we modify it." solutions: - approach_name: Ternary Digit Check is_optimal: true code: | def check_powers_of_three(n: int) -> bool: # Check each digit in base-3 representation while n > 0: # Get the rightmost digit in base 3 if n % 3 == 2: # Digit 2 means we'd need to use a power twice return False # Remove the digit we just checked n //= 3 # All digits were 0 or 1 return True explanation: | **Time Complexity:** O(log n) — We divide by 3 each iteration, processing log_3(n) digits. **Space Complexity:** O(1) — Only uses the input variable. We convert `n` to base 3 on the fly, checking each digit. If any digit equals 2, we need that power of 3 twice, which violates the distinct requirement. If all digits are 0 or 1, the sum is valid. - approach_name: Greedy Subtraction is_optimal: false code: | def check_powers_of_three(n: int) -> bool: # Find the largest power of 3 <= n power = 1 while power * 3 <= n: power *= 3 # Greedily subtract powers of 3 while n > 0 and power > 0: if power <= n: n -= power power //= 3 return n == 0 explanation: | **Time Complexity:** O(log n) — Two passes through powers of 3. **Space Complexity:** O(1) — Only tracking `power` and `n`. We greedily subtract the largest possible power of 3 at each step, using each power at most once. If we reduce `n` to 0, the answer is true. This is equivalent to the ternary approach but less elegant — it's harder to see why it works. - approach_name: Subset Sum with Powers is_optimal: false code: | def check_powers_of_three(n: int) -> bool: # Generate all powers of 3 up to n powers = [] power = 1 while power <= n: powers.append(power) power *= 3 # Use recursion to check if any subset sums to n def can_sum(index: int, remaining: int) -> bool: if remaining == 0: return True if remaining < 0 or index == len(powers): return False # Include or exclude current power return (can_sum(index + 1, remaining - powers[index]) or can_sum(index + 1, remaining)) return can_sum(0, n) explanation: | **Time Complexity:** O(2^k) where k = log_3(n) — potentially checking all subsets. **Space Complexity:** O(k) — recursion depth and powers array. This brute force approach tries all combinations of powers of 3. While it works for the given constraints (k <= 15), it's much slower than the O(log n) ternary approach. Included to show the connection to subset sum problems.