Codility刷题之旅 - Exercise9 - Bitwise operations (bit-ops)

512 阅读3分钟

Exercise9 - Bitwise operations(bit-ops)

BinaryGap: Find longest sequence of zeros in binary representation of an integer.

题目概述:这题在Lessons部分已经解过了,就是Lessons1的第一题,不知道为啥会在这里再出现一次

解法概述:题目和解法就都不再赘述了,可以参看之前文章:juejin.cn/post/719891…

CountConformingBitmasks: Count 30-bit bitmasks conforming to at least one of three given 30-bit bitmasks.

image.png

问题概述:本题输入是三个30位的无符号整数A、B、C。并且定义了一个conforms to的概念:如果a conforms to b,则代表了b的30位中为1的部分,a的30位数中的对应部分一定也是1。本题需要的返回,是基于输入的A、B、C,一共可以找到多少种不同的30位无符号整数,符合conform to A、B、C中的至少一个。

解法概述:本题解法的思考,是本题的关键。事实上如果想清楚了那么solution函数将会非常简单。

问题需求的解,是conform to A、B、C中至少一个的不同30位整数。首先我们不难想通,以A、B、C中任何一个来说(这里以A为例),能符合conform to A条件的30位无符号整数,一共有2的k次方,k就是A中0的个数。因此我们可以分别根据A、B、C中0的个数,算出对应的2的k次方并加总,也就是下方solutions里的第一行。

然后这样简单的加总,很可能会存在重复的解,想要去掉这些重复的解,而这个重复解的个数,是可以通过A、B、C两两组合后进行或(|)运算,再根据新的30位无符号整数中0的个数,计算2的k次数得到。这样减完之后,就像注释所述,还需要再把(A|B|C)的30位无符号整数对应的2的k次数加回去,就能得到最终的不重复30位无符号整数总数了。

def supers(number):
    N = 30
    zeros = sum(1 for bit in range(N) if (number >> bit) & 1 == 0)
    return 2**zeros

def solution(A,B,C):
    total = supers(A) + supers(B) + supers(C)
    total -= supers(A | B) # counted twice, remove one
    total -= supers(B | C) # counted twice, remove one
    total -= supers(A | C) # counted twice, remove one
    total += supers(A | B | C) # counted three times, removed three times, add one
    return total

image.png

SparseBinaryDecomposition: Decompose int into sum of ints having no consecutive 1s in binary form.

image.png

问题概述:本题输入是一个正整数N,然后定义了对正整数N的二进制的sparse decomposition操作,定义就是拆分为两个二进制之和后,两个二进制数都不存在连续的1。可能是存在多种符合条件的sparse decomposition的,而需要的返回值,是所有符合条件的sparse decomposition中任意一个值即可。

解法概述:本题还是贪婪算法求解,首先将N转为二进制,然后从第一位的1开始,利用贪婪算法的思想得到一组符合sparse decomposition的解bin_a,bin_b,其中bin_a>bin_b(因为第一位的1给了bin_a)。最终将bin_a转回10进制返回即可。

def solution(N):
    # 转二进制
    str_bin_N = ''
    while N>0:
        str_bin_N = str(N%2)+str_bin_N
        N = N//2
    
    # 二进制使用贪婪算法找到一个可行解
    bin_a, bin_b = '', ''
    pre_v = '0'
    for v in str_bin_N:
        if pre_v=='1':
            bin_a += '0'
            bin_b += '1'
            pre_v = '0'
        else:
            bin_a += v
            bin_b += '0'
            pre_v='1'
    
    # bin_a转回十进制
    res = 0
    for i, v in enumerate(bin_a[::-1]):
        res += int(v)*2**i
    return res 

image.png