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.The problem asks to find the smallest base k
such that the given integer n
can be represented as a number with all digits being 1 in base k
. This means we're looking for a k
that satisfies the equation:
n = 1 + k + k^2 + ... + k^(m-1)
where m
is the number of digits in the base k
representation. This is a geometric series, which can be simplified to:
n = (k^m - 1) / (k - 1)
Rearranging the equation, we get:
n * (k - 1) = k^m - 1
n * k - n = k^m - 1
We can solve this by trying different values of m
and using binary search to find k
for each m
.
Approach:
Iterate through possible values of m
: We iterate from m = 63
down to 2. The upper bound of 63 comes from the fact that 2^63
is larger than the maximum value of n
(1018). This is because the maximum possible value for m
is roughly log2(n)
. Starting from a large m
ensures that we find the smallest base first.
Binary Search for k
: For each value of m
, we use binary search to find the integer k
that satisfies the equation. The search space for k
is [2, n-1]. We check if (k^m - 1) / (k - 1)
equals n
. If it does, we've found a good base k
.
Handle the Case m = 1
: If the loop completes without finding a solution, it means that n
is a power of 2 minus 1. In that case, the smallest good base is n-1
.
Time Complexity Analysis:
m
).Space Complexity Analysis:
The space complexity is O(1) because we use only a constant amount of extra space to store variables.
Code Explanations (Python3 as an example):
The Python code directly implements the above approach. Let's break down the key parts:
def smallestGoodBase(self, n: str) -> str:
num = int(n) # Convert n to integer for calculations
for m in range(63, 1, -1): # Iterate through possible values of m
l, r = 2, num - 1 # Initialize binary search range
while l < r: # Binary Search
mid = (l + r) // 2 # Integer division
s = sum(mid**i for i in range(m)) # Calculate sum of geometric series
if s >= num: # Check if sum is greater than or equal to n
r = mid # Adjust search range
else:
l = mid + 1 # Adjust search range
if sum(l**i for i in range(m)) == num: # Check if solution is found
return str(l) # Return the smallest good base
return str(num - 1) # Handle case where m=1
The other languages (Java and C++) follow the same logic but handle potential integer overflow issues more carefully due to the larger numbers involved in the calculation. They use similar binary search and geometric series summation techniques. The C++ version uses pow()
function and requires careful handling of potential floating-point errors. The Java version uses a custom function (calc()
) to handle large numbers safely.