Smallest Good Base

The task requires us to find the smallest base ( k \geq 2 ) such that all digits of the given number ( n ) when represented in base ( k ) are 1’s.

We can find this base by trying to represent ( n ) in different bases and checking if all the digits are 1’s. We’ll need to derive a formula for the sum of a geometric progression and use binary search to find the correct base.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Solution:
    def smallestGoodBase(self, n: str) -> str:
        n = int(n)

        # We'll iterate through possible lengths of 1's in base k representation
        for m in range(n.bit_length(), 1, -1):
            # Using binary search to find base k for given length m
            k = int(pow(n, 1 / (m - 1)))
            if (k ** m - 1) // (k - 1) == n:
                return str(k)

        return str(n - 1)

Explanation:

  • The loop iterates through possible lengths ( m ) of the representation of ( n ) in base ( k ).
  • The formula ((k^m - 1) / (k - 1) = n) comes from the sum of a geometric progression where all digits are 1’s.
  • The base ( k ) that satisfies this equation for a given ( m ) can be found using binary search.
  • If the base is found, we return it. If not, the result will be ( n-1 ), which is the base for a number that consists of two 1’s.

10 Prerequisite LeetCode Problems

Here are some problems that focus on binary search, mathematical properties, and number theory to prepare for the problem “483. Smallest Good Base”:

  1. 69. Sqrt(x)
  2. 367. Valid Perfect Square
  3. 441. Arranging Coins
  4. 540. Single Element in a Sorted Array
  5. 704. Binary Search
  6. 74. Search a 2D Matrix
  7. 365. Water and Jug Problem
  8. 172. Factorial Trailing Zeroes
  9. 231. Power of Two
  10. 326. Power of Three
1
2
3
4
5
6
7
8
class Solution:
    def smallestGoodBase(self, n: str) -> str:
        n = int(n)
        for m in range(int(math.log(n, 2)), 1, -1):
            k = int(n ** m ** -1)
            if (k ** (m + 1) - 1)
                return str(k)
        return str(n - 1)

Problem Classification

The task is to find the smallest base with which a number can be expressed as all ones. This is a Base Conversion Problem.

Language Agnostic Coding Drills

To break down the problem, we can identify the following fundamental concepts:

  1. Mathematical operations: This includes conversion of data types, taking powers, and subtracting numbers. These operations form the basis of the algorithm implemented in this function.

  2. Looping constructs: The function uses a for loop which iterates over a range of values in descending order. Understanding how loops work is essential to grasp the flow of this algorithm.

  3. Conditional statements: A condition is checked inside the loop, which when satisfied, determines the output of the function.

Now let’s break down the problem-solving approach step by step:

  1. The problem requires us to find the smallest base (k) for a number (n) that satisfies the condition that n can be represented as a sum of powers of k, where the power starts from 0 and increments by 1 for each term.

  2. The initial input is a string, so we convert it to an integer for our calculations.

  3. We start by finding the maximum possible value of m, which is the number of terms in the series (or powers of k). This can be obtained by taking the logarithm to the base 2 of n. We start from this maximum value and go down to 2 (as having m=1 is trivial, every number can be represented as a power of 1).

  4. For each m, we calculate k (the base) by taking the m-th root of n (or raising n to the power of -1/m).

  5. We then check if n can be represented as a sum of m+1 terms with base k (or if k is a valid base for n for the given m). The formula to calculate the sum of first m+1 terms in a geometric series where each term is a power of k is k^(m+1) - 1. If this is equal to n*(k-1), then we have found our answer and return k as a string.

  6. If no such k is found after checking for all m from max_m to 2, then the base will be n-1, as n can be represented as n-1 raised to the power 1 plus 1.

To be able to code this solution from scratch, one needs to understand and practice concepts like looping, mathematical operations, and condition checking. By tackling smaller problems or drills related to these concepts, one can gradually build up to implementing this solution.

Targeted Drills in Python

To fully understand the given solution, we can start by practicing the basic skills needed. Below are coding drills for each concept needed in Python.

  1. Mathematical operations:

    Coding Drill: Write a function that takes two numbers as inputs, converts them to integers, raises the first number to the power of the negative inverse of the second number, and returns the result.

    1
    2
    3
    4
    5
    6
    
    def power_operation(base: str, exponent: str) -> float:
        base = int(base)
        exponent = int(exponent)
        result = base ** (-1 / exponent)
        return result
    print(power_operation("16", "2"))
    
  2. Looping constructs:

    Coding Drill: Write a function that iterates over a range of numbers in reverse order and prints each number.

    1
    2
    3
    4
    
    def reverse_loop(start: int, stop: int) -> None:
        for i in range(start, stop, -1):
            print(i)
    reverse_loop(10, 1)
    
  3. Conditional statements:

    Coding Drill: Write a function that checks if a number can be represented as the sum of all powers of another number up to a certain limit, and returns a boolean.

    1
    2
    3
    4
    5
    6
    
    def check_sum(n: int, base: int, limit: int) -> bool:
        total_sum = 0
        for i in range(limit + 1):
            total_sum += base ** i
        return total_sum == n
    print(check_sum(31, 2, 4))
    
  4. Problem specific drill:

    Coding Drill: Implement the formula to calculate the sum of a geometric series and check if it’s equal to a given number multiplied by (base - 1). Return a boolean result.

    1
    2
    3
    4
    
    def check_geometric_sum(n: int, base: int, limit: int) -> bool:
        geometric_sum = (base ** (limit + 1) - 1) // (base - 1)
        return geometric_sum == n
    print(check_geometric_sum(31, 2, 4))
    

By working through these drills, you’ll have practiced the individual parts of the final solution, making it easier to understand how they all fit together.