483 最小好进制(数学、二分查找)

44 篇文章 1 订阅
41 篇文章 0 订阅
该博客讨论了如何解决LeetCode上的'最小好进制'问题,即找到使整数n的所有数位全为1的最小进制。文中提出了两种解决方案:数学方法和二分查找法。通过设置方程和迭代,这两种方法都尝试找到满足条件的最小k值。代码示例展示了如何在Python中实现这些方法。
摘要由CSDN通过智能技术生成

1. 问题描述:

对于给定的整数 n, 如果n的k(k>=2)进制数的所有数位全为1,则称 k(k>=2)是 n 的一个好进制。以字符串的形式给出 n, 以字符串的形式返回 n 的最小好进制。

示例 1:
输入:"13"
输出:"3"
解释:13 的 3 进制是 111。

示例 2:
输入:"4681"
输出:"8"
解释:4681 的 8 进制是 11111。

示例 3:
输入:"1000000000000000000"
输出:"999999999999999999"
解释:1000000000000000000 的 999999999999999999 进制是 11。
提示:
n的取值范围是 [3, 10^18]。
输入总是有效且没有前导 0。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/smallest-good-base

2. 思路分析:

① 对于这种题目我们可以从代数的角度来表示成一个对应的式子,根据题目的描述,我们不妨设n由k进制下的0,1,2...m位1构成的,这样就可以n就可以表示成k和m的方程,表示成方程之后我们的目标是找到m,k使得这个方程成立,我们可以大概估计一下m的位数,分析题目可以知道k >= 2,所以如果n是由2进制构成的全1的字符串那么最多的位数应该是log2n向上取整位。所以我们可以枚举当前可能的位数,在枚举位数的时候那么m就确定了,但是我们怎么样确定k呢?分析题目可以知道k最大是n - 1,也即由2个1构成的字符串,如果暴力枚举的话肯定超时的,其实我们可以由上面的方程得到k大概的范围,因为枚举m的时候n,m都是确定的要想等式尽可能成立那么k一定是与n,m存在某种关系的,当我们得到k的范围之后那么剩下的工作就好办了,其中的证明过程如下。通过下面的证明我们可以得到k的具体值,通过计算当前m位k进制1是否等于n判断等式是否成立(暴力枚举的思想)。因为n一定的情况下m越大k一定越小,所以我们在枚举m的时候可以从大到小进行枚举,这样当我们找到答案之后对应的k肯定是最小的。

② 由①可知,当我们在枚举m位1的时候需要确定k,因为k越大那么对应的n是越大的所以我们可以使用二分来计算出当前k,在二分的时候计算k进制下m + 1位1对应的数字,判断是否等于n,两种做法都是基于暴力枚举的思想,都在尝试可能的m,k使得等式成立。

3. 代码如下:

数学:

import math


class Solution:
    def smallestGoodBase(self, n: str) -> str:
        n = int(n)
        if n <= 3: return str(n - 1)
        m_max = int(math.log(n, 2)) + 1
        for m in range(m_max, 1, -1):
            k = int(math.pow(n, 1.0 / m))
            t = 0
            # 计算k进制m + 1的1的结果
            for j in range(m + 1):
                t = t * k + 1
            if t == n: return str(k)
        return str(n - 1)

二分:

import math


class Solution:
    def smallestGoodBase(self, n: str) -> str:
        n = int(n)
        if n <= 3: return str(n - 1)
        m_max = int(math.log(n, 2)) + 1
        for m in range(m_max, 1, -1):
            l, r = 2, 10 ** 18
            while l <= r:
                k = l + r >> 1
                t = 0
                for j in range(m + 1):
                    t = t * k + 1
                if t == n: return str(k)
                if t > n:
                    r = k - 1
                else:
                    l = k + 1
        return str(n - 1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值