LeetCode 483 Smallest Good Base

定义:
good base:当n在k进制下的数每一位都是1,则称k是n的good base
需求:找出n的最小good base
思路:二分查找


  1. 给一个n,n∈[3,10^18]
  2. n-1一定是n的good base
  3. good base 越小位数越多

    • 例如:13 goodbase 有12,3
    • 12进制下是11
    • 3进制下是111

//伪代码
num输入的数字
ans记录goodbase,初始化ans=num-1left=2,right=n-2,mid=(left+right)/2
外循环:1的位数j,j>=3
    find=0//发现标志
    内循环:left<=right //查找[left,right]区间满足j1goodbase
        1.计算mid结果temp = mid^0+mid^1+...+mid^(j-1)
        2.判断结果是否溢出,溢出:right = mid-1,mid = (right+left)/2
        3.temp==num,找到一个goodbase,用ans记录,find=1,更新发现标志
        2.temp>num,right = mid-1,mid = (right+left)/2
        3.temp<num,left = mid+1,mid = (right+left)/2
    find==0说明没找到,更新left=2,right=left-1 //left停留的位置计算出来一定是大于nright<2的时候说明从[2,num-2]所有的goodbase都遍历过了,break


例如13
ans = 12
left=2,right=11,mid=6

j = 3 //111
    left<right,temp=1+6+36=43,temp>ans,right=mid-1=5,mid=(2+5)/2=3 //left=2,right=5,mid=3
    left<right,temp=1+3+9=13,temp==ans,ans=mid,find=1,right=mid-1=2,left=2,mid=2//left=2,right=2,mid=2
j = 4 //1111
    left==right,temp=1+2+4+8=15,temp>ans,right=mid-1=1,mid=(2+1)/2=1 //left=2,right=1,mid=1
    right<2:break;
ans=3

//java
import java.math.BigInteger;
class Solution {
        public String smallestGoodBase(String n) {
        long num = 0;
        char[] c_num = n.toCharArray();
        for(int i=0;i<n.length();i++) {
            num = num*10+c_num[i]-'0';
        }
        if(num<3) return null;
        long ans = num-1; //11
        long left = 2;
        long right = ans-1;
        long mid = (left+right)>>1;
        int find = 0;

        for(int j=3;;j++) {//从111开始逼近
            find = 0;
            while(left<=right) {
                long temp = calc(mid,j);//a^0+a^1+a^2...a^j-1
                if(temp==-1) {
                    //溢出的数据按照temp>num处理
                    right = mid - 1;
                    mid = (left+right)>>1;
                }
                else if(temp==num) {
                    ans=mid;
                    find = 1;
                    right = mid-1;
                    left = 2;
                    mid = (left+right)>>1;
                    break;
                }else if(temp<num){
                    left = mid + 1;
                    mid = (left+right)>>1;
                }else {
                    right = mid - 1;
                    mid = (left+right)>>1;
                }
            }
            if(right<2)//遍历到j位的时候已经没有进制满足了
                break;
            if(find==0) {
                right = left-1;
                left = 2;
                mid = (left+right)>>1;
            }
        }

        return new Long(ans).toString();
    }
    public long calc(long num,long num1) {//num
        if(num>=999999999) return -1;
        BigInteger ans = new BigInteger("0");
        BigInteger number = new BigInteger(new Long(num).toString());
        for(int i=0;i<num1;i++) {
            if(i==0)
                ans = ans.add(new BigInteger("1"));
            else {
                BigInteger temp = new BigInteger("1");
                for(int j=0;j<i;j++) {
                    temp = temp.multiply(number);
                }
                ans = ans.add(temp);
            }
        }
        String ttemp = ans.toString();
        char[] ans2 = ttemp.toCharArray();
        if(ttemp.length()>=20) return -1;
        if(ans2.length==19) {
            if(ans2[0]>'1') return -1;
            else {
                for(int ff=1;ff<ttemp.length();ff++) {
                    if(ff!='0')
                        return -1;
                }
            }
        }
        long ans3 = 0;
        for(int ii=0;ii<ttemp.length();ii++) {
            ans3 = ans3*10 + ans2[ii]-'0';
        }

        return ans3;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值