leetcode
leetcode 401 ~ 450
最小好进制

最小好进制

难度:

标签:

题目描述

以字符串的形式给出 n , 以字符串的形式返回 n 的最小 好进制  。

如果 n 的  k(k>=2) 进制数的所有数位全为1,则称 k(k>=2) 是 n 的一个 好进制 

 

示例 1:

输入:n = "13"
输出:"3"
解释:13 的 3 进制是 111。

示例 2:

输入:n = "4681"
输出:"8"
解释:4681 的 8 进制是 11111。

示例 3:

输入:n = "1000000000000000000"
输出:"999999999999999999"
解释:1000000000000000000 的 999999999999999999 进制是 11。

 

提示:

  • n 的取值范围是 [3, 1018]
  • n 没有前导 0

代码结果

运行时间: 32 ms, 内存: 16.0 MB


/*
 * 思路:
 * 通过二分查找确定 k,使得 n 能被表示成 k 进制的全1形式。
 * 使用 Java Stream 进行流式操作,利用 IntStream 进行范围遍历。
 */
 
import java.util.stream.IntStream;
 
public class Solution {
    public String smallestGoodBase(String n) {
        long num = Long.parseLong(n);
        return IntStream.rangeClosed(2, (int)(Math.log(num + 1) / Math.log(2)))
            .mapToObj(m -> new Object() {
                long k = (long)(Math.pow(num, 1.0 / m));
                long sum = IntStream.rangeClosed(0, m).mapToLong(i -> (long) Math.pow(k, i)).sum();
            })
            .filter(obj -> obj.sum == num)
            .map(obj -> String.valueOf(obj.k))
            .findFirst()
            .orElse(String.valueOf(num - 1));
    }
}

解释

方法:

题解利用等比数列的求和公式,结合枚举所有可能的数列长度 m (从 n 的二进制长度递减至 2) 来找到最小的好进制。对于每个 m,首先计算可能的基数 x = n的(m-1)次方根,然后验证 x 是否能够使得 n 等于从 1 到 x^(m-1) 的等比数列和。如果满足条件,即为所求的最小好进制。

时间复杂度:

O(log(n))

空间复杂度:

O(1)

代码细节讲解

🦆
在题解中,你是如何估算等比数列求和公式 `n = (x^m - 1) / (x - 1)` 中的基数 `x` 和长度 `m` 的关系?
在题解中,为了找到合适的基数 `x` 使等式 `n = (x^m - 1) / (x - 1)` 成立,首先需要确定序列的长度 `m`。给定长度 `m` 后,可以将公式重写为 `x^m - 1 = n * (x - 1)`,进而估算基数 `x`。利用 `x` 的最大可能值为 `n` 的 `(m-1)` 次方根,可以通过计算 `int(pow(num, 1/(m-1)))` 来近似得到 `x`。这种估算是基于等比数列求和公式的数学推导,确保 `x` 和 `m` 的选择能满足原始等式。
🦆
为什么题解选择从 `n` 的二进制长度递减至 2 遍历数列长度 `m`?这样的递减遍历对算法的效率有何影响?
选择从 `n` 的二进制长度递减至 2 遍历 `m` 是基于最小好进制的特性。当 `n` 用二进制表示时,长度最长时其基数为 `2`,这是可能的最大长度。从这个长度开始递减至 2,可以有效地找到最小的 `m` 使得存在对应的基数 `x`。这种递减遍历方式有助于尽快找到满足条件的最小 `x`,因为较小的 `m` 对应较大的 `x`,而我们的目标是找到最小的好进制,即最小的 `x`。从效率上看,这种方法减少了不必要的计算,因为从小的 `m` 开始并不总是能迅速找到满足条件的基数。
🦆
题解中提到对每个可能的长度 `m`,计算 `x` 为 `n` 的 `(m-1)` 次方根,这种计算方法在哪些情况下可能不准确,如何改进?
计算 `x` 为 `n` 的 `(m-1)` 次方根可能在精度上存在问题,特别是当 `m` 较大或 `n` 较大时,由于浮点数运算的精度限制,计算得到的 `x` 可能不是整数或者四舍五入后的结果可能与实际的整数解有差距。这种不准确性可能导致无法准确验证 `n = (x^m - 1) / (x - 1)`。为了改进这个问题,可以采用整数二分查找方法来更精确地寻找可能的基数 `x`。在一个合理的范围内(例如从 `2` 到 `n-1`),通过二分查找逐步逼近正确的 `x`,同时每次迭代都验证是否满足等比数列求和公式,这样可以更精确地确定 `x`。

相关问题