LeetCode 483. 最小好进制

难度:困难。
标签:数学,二分查找。

这个题,太绕了,浓浓的数学味,想不到方法。
没有看数学方法的解答,看了个比较容易想到的方法,但是也很绕,想不到一个条件就写不出来。
使用二分法进行解答。

  1. 给定n后,首先确定全为1的k进制串的最长长度,当为二进制数时,长度是最长的,因此最长度为 M a x L e n = l o g 2 n + 1 MaxLen=log_2n + 1 MaxLen=log2n+1
  2. 为了使k最小,则从最长长度MaxLen开始遍历,得到的第一个符合条件的就是k最小的情况。
    确定了len后,确定k的范围,k的范围最小为2,最大满足 k ( l e n − 1 ) < x k^{(len-1)}<x k(len1)<x,则最大k取 x ( 1 / ( i − 1 ) ) x^{(1/(i-1))} x(1/(i1))
  3. 确定k的范围后,使用二分法进行查找,get函数得到k进制,长度为len的进制串的大小(10进制表示)。

注意与n,k相关的都要使用unsigned long long类型。

正确解法:

class Solution {

    // k^0 + k^1 + ... + k^(len - 1)
    unsigned long long get(unsigned long long k, int len){
        unsigned long long res = 1;
        unsigned long long temp = 1;
        for(int i = 1; i < len; ++i){
            temp *= k;
            res += temp;
        }
        return res;
    }


public:
    string smallestGoodBase(string n) {
        unsigned long long x = stoull(n);
        int max_len = log(x) / log(2) + 1;
        for(int i = max_len; i >= 3; --i){
            unsigned long long left = 2, right = (unsigned long long)pow(x, (double)1 / (i - 1));
            while(left <= right){
                unsigned long long mid = (left + right) / 2;
                unsigned long long y = get(mid, i);
                if(y == x)return to_string(mid);
                else if(y > x)right = mid - 1;
                else left = mid + 1;
            }
        } 
        return to_string(x - 1);
    }
};

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值