leetcode每日一题系列-最小好进制

164 阅读2分钟

leetcode-483-最小好进制

[博客链接]

一个菜🐔的学习之路

掘金首页

[题目描述]

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

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



 示例 1: 


输入:"13"
输出:"3"
解释:133 进制是 111。


 示例 2: 


输入:"4681"
输出:"8"
解释:46818 进制是 11111。


 示例 3: 


输入:"1000000000000000000"
输出:"999999999999999999"
解释:1000000000000000000999999999999999999 进制是 11。




 提示: 


 n的取值范围是 [3, 10^18]。 
 输入总是有效且没有前导 0。 



 Related Topics 数学 二分查找 
 👍 65 👎 0

[题目链接]

leetcode题目链接

[github地址]

代码链接

[思路介绍]

思路一:等比数列求和公式

  • Sn=a1anq1qS_n=\dfrac{a_1-a_nq}{1-q} (q是公比 n是s转换成q进制后1的个数)
  • n越大q越小n最大不超过**(s-1)**
  • 因为s一定可以转换成s-1进制的好进制格式即11
  • 因为求的是最小好进制
  • 所以可以从最小公比开始遍历遍历范围**[2,s-1]**标识为公比
  • i= 2开始推出tempT = s*(i-1)+1
  • 判断tempT的最大这种方法会TLE
public String smallestGoodBase(String s) {
            long target = Long.parseLong(s);
            for (long i = 2; i < target; i++) {
                long tempT = target * (i - 1) + 1;
                //排除不满足的i情况
                if (tempT % i != 0) {
                    continue;
                }
                //判断是否能够满足tempT是i的n次幂
                while (tempT % i == 0 && tempT != i) {
                    tempT /= i;
                }
                if (tempT == i) {
                    return String.valueOf(i);
                }
            }
            return String.valueOf(target - 1);
        }

时间复杂度O(n*logn)


思路二:思路一+不等式推倒

  • 思路一确定有解
  • tempT=in<sitempT = i^n<s*i
  • n<logis+1<60n<log_i^s + 1<60
  • 再根据二项式定理(官方题解可以推出i = nm \sqrt[m]{n}的下线整数)

image-20210618100155308

  • 根据n从最大值开始枚举满足条件的i的数,第一个遇到的即为k的最小值(n标识i进制位数)
public String smallestGoodBase(String s) {
            long nVal = Long.parseLong(s);
            int mMax = (int) Math.floor(Math.log(nVal) / Math.log(2));
            for (int n = mMax; n > 1; n--) {
                int i = (int) Math.pow(nVal, 1.0 / n);
                long mul = 1, sum = 1;
                for (int t = 0; t < n; t++) {
                    mul *= i;
                    sum += mul;
                }
                if (sum == nVal) {
                    return Integer.toString(i);
                }
            }
            return Long.toString(nVal - 1);
        }

时间复杂度(O(log2nlog2nlog_2^n*log_2^n))