📜  从0到N的连续数字的汉明差总和|套装2(1)

📅  最后修改于: 2023-12-03 15:06:32.923000             🧑  作者: Mango

从0到N的连续数字的汉明差总和|套装2

简介

这是一个用于求解从0到N的连续数字的汉明差总和的算法,也称之为连续子段汉明差总和。该算法属于动态规划(DP),其时间复杂度为O(N*logN)。

算法实现

该算法的具体实现步骤如下:

  1. 将整数N转化成二进制表示,得到一个长度为M的01串。

    例如,当N=19时,其二进制表示为"10011",那么M=5。

  2. 以1到M为下标,对每个下标i,求解f[i]和g[i]。

    其中,f[i]代表以N的二进制表示中第i位为结尾的所有01串中差值为1的数量之和,g[i]代表以N的二进制表示中第i位为结尾的所有01串中差值为0的数量之和。

    初始值为f[1]=0,g[1]=1,然后根据下面的递推公式计算f[i]和g[i]:

    f[i] = f[i-1] + g[i-1]
    g[i] = 2*g[i-1]
    

    其中,f[i]的值可以由f[i-1]和g[i-1]递推得到,因为f[i-1]中的所有01串都会在f[i]中产生一个汉明距离为1的01串,而g[i-1]中的所有01串,都可以在f[i]中和之前的01串组合产生一个汉明距离为1的01串。g[i]的值可以由g[i-1]递推得到,因为g[i-1]中的所有01串都可以在g[i]中产生一个汉明距离为0的01串,而g[i-1]中的所有01串再加上一个新的"0"或"1"也可以组成g[i]中的所有01串。

  3. 最后,根据下面的公式计算从0到N的连续数字的汉明差总和:

    sum = 0
    for i in range(1, M+1):
        sum += i*(f[i]+g[i])
    

    其中,i代表从0到i-1产生一个汉明距离为1的所有01串,即若i=3,那么i-1=2-bin="010",则对应的所有01串为"011"和"001",共计2个。f[i]+g[i]即代表以第i位为结尾的所有01串中其中一个数字减去前一个数字的差值之和。i*(f[i]+g[i])即代表以第i位为结尾的所有01串中其中一个数字减去前一个数字的差值之和,乘以i产生的贡献,即i产生的汉明差总和。

代码实现

下面是该算法的实现代码:

def hammingDiffSum(N):
    M = len(bin(N))-2
    f = [0]*(M+1)
    g = [1]*(M+1)
    for i in range(2, M+1):
        f[i] = f[i-1] + g[i-1]
        g[i] = 2*g[i-1]
    sum = 0
    for i in range(1, M+1):
        sum += i*(f[i]+g[i])
    return sum
总结

该算法是一个比较巧妙的DP算法,其时间复杂度为O(N*logN),空间复杂度为O(logN)。对于大部分数据范围在10^9以内的题目,该算法可以很好地解决问题。