n的p进制下的数码之和问题

hammingWeight的动态规划

以前做过一道题(191. Number of 1 Bits )讲的是给定一个数,求它二进制下的1的个数。如果是对于一个数,那么可以用位运算黑魔法:(对末尾做与1的与运算)

class Solution(object):
    def hammingWeight(self, n):
        ans=0
        while n:
            if n&1==1:
                ans+=1
            n=n>>1
        return ans

今天碰到了一个进阶版的题目,(338. Counting Bits )题目要求是在 O(n) 的时间和空间里计算出 [0,n] 区间里所有整数的二进制下的1的个数(Hamming weight - Wikipedia)。

O(n) 的时间要求是有点小苛刻的,首先遍历一次 [0,n] 区间里所有整数就需要 O(n) ,那么每次小操作需要在 O(1) 内才是可以的,首先想到的是能不能用上面leetcode191的做法来套用呢?不妨分析一下复杂度。

容易看出对于一个数 n ,这样的操作(主要是移位操作)时间复杂度是O(log2n),那么利用斯特林公式可以估算区间 [0,n] 区间里所有整数就需要大约

T(n)=i=1nlog2i=log2n!log2nn=nlog2n

很遗憾的是并不能直接满足题目中所要求的 O(n) 复杂度,如果消耗一点空间换时间,利用上述的方法还是有机会降到 O(n) 的动态规划的思路:

res 表示最终的结果,改写上述方法为一个一维的递推式:

res(n)=res([n2])+n&1

也就是说一直维护这样的一个一维数组,每次都记录其结果,显然时间复杂度是 O(n) ,空间也是 O(n) ,满足题目要求。不过这并不是我首先想到的思路,我首先想到的是,直接从n的p进制下的数码之和角度入手。

class Solution(object):
    def countBits(self, num):
        ans=[0]
        for x in range(1,num+1):
            ans+=[ans[x>>1]+(x&1)]
        return ans

n的p进制下的数码之和

Sp(n) 表示n的p进制下的数码之和,用 ap 表示 n! 的标准分解中 p 的幂次,即papn!,但 pap+1|n! 。首先写出表达式:

n=akpk+...+a1p+a0=(ak...a1a0)p

容易得出每一项系数的准确公式:
ai=[npi]p[npi+1]

接着进行一下数学推导:

Sp(n)=i=0kai=i=0k[npi]pi=0k[npi+1]=n+i=1k[npi]pi=0k[npi+1]=n(p1)i=1k[npi]p[npk+1]=n(p1)i=1[npi]0=n(p1)ap

这个推导需要用到勒让德公式,即 n! p 的幂次为i=1[npi] ,显然这种办法主要复杂度回耗在勒让德公式上,可以观察到 p 的幂次i达到 logpn 时候,勒让德公式后面的每一项均为0,即对于二进制而言,完成一次勒让德运算需要 O(log2n) ,那么对于原问题一共需要 O(nlog2n) 的时间。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值