Given an integer n represented as a string, return the smallest good base of n.
We call k >= 2 a good base of n, if all digits of n base k are 1's.
Example 1:
Input: n = "13" Output: "3" Explanation: 13 base 3 is 111.
Example 2:
Input: n = "4681" Output: "8" Explanation: 4681 base 8 is 11111.
Example 3:
Input: n = "1000000000000000000" Output: "999999999999999999" Explanation: 1000000000000000000 base 999999999999999999 is 11.
Constraints:
n is an integer in the range [3, 1018].n does not contain any leading zeros.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
We want to find the smallest 'base' number that can be used to represent a given number using only 1s. The brute force approach involves trying every possible base and checking if it works.
Here's how the algorithm would work step-by-step:
def smallest_good_base_brute_force(number_as_int):
# Iterate through potential bases starting from 2
for base_candidate in range(2, number_as_int):
sum_of_powers = 0
power_of_base = 1
exponent = 0
# Construct number from 1s in the current base
while sum_of_powers < number_as_int:
sum_of_powers += power_of_base
power_of_base *= base_candidate
exponent += 1
# Check if the sum equals the number
if sum_of_powers == number_as_int:
return base_candidate
# If no good base is found, the number - 1 is the smallest
return number_as_int - 1The challenge is to find the smallest number, let's call it 'k', such that a number 'n' can be expressed as a sum of powers of 'k'. The best approach involves cleverly searching for possible values of 'k' by first figuring out the possible number of terms in the sum and then narrowing down the search range to find the best 'k'.
Here's how the algorithm would work step-by-step:
def smallestGoodBase(number): number_as_integer = int(number)
maximum_number_of_terms = number_as_integer.bit_length()
for number_of_terms in range(maximum_number_of_terms, 1, -1):
left_bound = 2
right_bound = pow(number_as_integer, 1 / (number_of_terms - 1))
while left_bound <= right_bound:
potential_base = (left_bound + right_bound) // 2
sum_of_powers = 0
for i in range(number_of_terms):
sum_of_powers += pow(potential_base, i)
if sum_of_powers == number_as_integer:
# We found a good base, return it as a string.
return str(potential_base)
elif sum_of_powers < number_as_integer:
# The base is too small; increase the lower bound.
left_bound = potential_base + 1
else:
# The base is too large; decrease the upper bound.
right_bound = potential_base - 1
# If no good base is found, n - 1 is always a good base.
return str(number_as_integer - 1)| Case | How to Handle |
|---|---|
| Input n is 1 | Return -1 since 1 can't be a good base because (1^m + 1^(m-1) + ... + 1^0) always equals m+1, which can only be equal to 1 when m=0, and m must be >=1. |
| Input n is a power of 2 | These cases often yield a base close to n-1 and should be handled efficiently by the search algorithm. |
| Integer overflow during base exponentiation | Use long data type for intermediate calculations and perform overflow checks during pow() operations by comparing the result with n / current_base. |
| Maximum possible input n (e.g., 10^18) | The binary search range for possible bases needs to be large enough to accommodate large n values and the solution must scale logarithmically to avoid TLE. |
| Cases where no good base exists | The binary search will converge to a low value; return the default value 'n-1' if no suitable base is found during search. |
| Base value equals 1 | The loop can break and return n-1 immediately if current base being tested is 1. |
| The smallest possible base value 2 results in an exponent of 1 | Ensure the initial value and bounds in the loop consider the scenario where only the largest potential exponent is used. |
| n is a prime number | The algorithm should still function correctly, potentially ending up testing base n-1 as that case can lead to the condition being met. |