LeetCode每日一题-2021-06-18-483. 最小好进制

在这里插入图片描述

个人思路

  1. 好进制一定在[2, n-1]之间
  2. n的好进制是k,那么应该存在一个i使得pow(k, i)/(i-1) == n,其中i[2, 60]之间,也就是1的个数,为啥是60,因为最大值是1e18,也就是1000e6 < 1024*2^6 = 2^60
  3. 当我们确定了一个进制和一个1的个数,那么可以唯一确定一个整数,而观察两个变量的范围,显然选择1个个数作为外循环,选择进制作为内循环,且因为是找固定递增区间中的固定的一个数字,因此首先考虑到二分
  4. 总的时间复杂度是O(logn)

直接贴代码

class Solution {
    public String smallestGoodBase(String n) {
        long nLong = Long.parseLong(n);
        long ans =nLong - 1;
        for(int numOne = 60; numOne >= 2; --numOne){
            long left = 2;
            long right = nLong-1;
            while( left <= right ){
                long mid = left + (right - left >> 1);
                long check = qinJiuZhao(nLong, mid, numOne);
                if( check == nLong ){
                    return String.valueOf(mid);
                }else if( check > nLong ){
                    right = mid - 1;
                }else{
                    left = mid + 1;
                }
            }
        }
        return String.valueOf(ans);
    }

    public long qinJiuZhao(long nLong, long base, int numOne){
        long num = 0;
        for(int i = 0; i < numOne; ++i){
            num = num * base + 1;
            if( i < numOne - 1 && num  > (nLong - 1) / base){
                return nLong + 1;
            }
        }
        return num;
    }
}

需要注意的几个点:如何把一个字符串变成基础数据类型的整数,如何把一个基础数据类型的整数变成字符串;秦九昭算法中,如何防止溢出,千万不能把不等号右边的乘到左边,乘过去不就又超了吗,(用个锤子秦九昭,直接按幂相加保证不超)

方法二:数学推导

直接看题解吧,懒得写了,都是在考虑遍历1的数量2-60,倒序,接着在给定len的情况下找一个进制k

class Solution {
    public String smallestGoodBase(String n) {
    	// (11...11)k = k^{s} + k^{s-1} + ... + k^1 + k^0 = n
        // k^s < n < (k+1)^s
        // k < n^{1/s} < k+1
        long nLong = Long.parseLong(n);
        long ans = nLong - 1;
        int numOneMax = (int) Math.floor(Math.log(nLong) / Math.log(2));//1的最大个数,至少为2,此时进制最大为n-1,其实默认60也行
        for (int m = numOneMax; m >= 2; m--) {
            long base = (long) Math.pow(nLong, 1.0 / m);
            long mul = 1, sum = 1;
            for (int i = 0; i < m; i++) {//这里没用秦九昭算法
                mul *= base;//为什么不会溢出可以思考一下
                sum += mul;
            }
            if (sum == nLong) {
                return Long.toString(base);
            }
        }
        return Long.toString(nLong - 1);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值