📌  相关文章
📜  二进制字符串的最长子序列可被3整除(1)

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

二进制字符串的最长子序列可被3整除

背景

二进制字符串是由0和1组成的字符串,而二进制字符串的最长子序列即为连续序列中的最长子序列,其中特定最长子序列可以被3整除。

题目

给定由0和1组成的二进制字符串S,找出它的最长子序列,使得该子序列所表示的二进制数能被3整除。如果有多个解,返回最短的一个子序列。如果没有符合条件的子序列,则返回空字符串。

思路

在二进制数中,每一位都有可能产生贡献,所以用0,1,2三个数分别记录,分别表示当前数字对3的余数是0,1,2。然后将数字一个一个读进来,如果是0就不管,因为它对和没有贡献,如果是1就让所有余数是1的位置加1,如果是2就让所有余数是2的位置加1。这样读完整个数字以后,最终三个余数的值都会被计算出来。如果当前总和对3取余数是x,那么要得到对3的余数对应的数字,就应该是余数为(x + 3) % 3的那个。

具体代码如下:

def get_longest_subsequence(s:str) -> str:
    length = len(s)
    first, second, third = length, length, length  # 记录余数为0,1,2的最后位置
    mod, cur = 0, 0  # cur记录当前数字对3的余数
    for i in range(length):
        if s[i] == '1':
            cur = (cur + 1) % 3
        elif s[i] == '2':
            cur = (cur + 2) % 3
        if cur == 0: # 余数为0
            first = min(first, i)
            mod = cur
        elif cur == 1: # 余数为1
            second = min(second, i)
            if first < length:
                mod = 1
        else: # 余数为2
            third = min(third, i)
            if second < length:
                mod = 2
    if mod == 0:
        return s[:length]
    if mod == 1:
        return s[first+1:second+1] if second < length else ''
    return s[first+1:third+1] if third < length else ''
时间复杂度

时间复杂度为O(n),其中n为字符串的长度。

空间复杂度

空间复杂度为O(1),只需要记录三个位置信息。

代码片段
def get_longest_subsequence(s:str) -> str:
    length = len(s)
    first, second, third = length, length, length  # 记录余数为0,1,2的最后位置
    mod, cur = 0, 0  # cur记录当前数字对3的余数
    for i in range(length):
        if s[i] == '1':
            cur = (cur + 1) % 3
        elif s[i] == '2':
            cur = (cur + 2) % 3
        if cur == 0: # 余数为0
            first = min(first, i)
            mod = cur
        elif cur == 1: # 余数为1
            second = min(second, i)
            if first < length:
                mod = 1
        else: # 余数为2
            third = min(third, i)
            if second < length:
                mod = 2
    if mod == 0:
        return s[:length]
    if mod == 1:
        return s[first+1:second+1] if second < length else ''
    return s[first+1:third+1] if third < length else ''