算法题题解记录——12. 最大UCC字串计算

131 阅读2分钟

题目

www.marscode.cn/practice/r3…

image.png

思路

  • 分析1

首先我们找UCC的个数,如果是UCC我们根本就不用动。 是否有一种可能原本是UCC,我们进行了一些操作后会有更多的UCC。其实没有,因为 “把UCC中的某个分配给左/右”,效果和“UCC不动直接向左/右插入他们想要的U/C”是一样的。

  • 分析2:

什么情况下用删除操作?直觉是删除可以用添加替代。哪种组合需要删除一个才能变成UCC?

UCUC => UCC(删除) 和 UCUC => UCCUC(插入)效果是一样的,甚至*插入更好。因为,多一个C就是多了一个拼成UCC的机会。所有的删除都可以用插入代替。

  • 分析3: 什么情况下用修改操作?把一个串修改一次变成UCC,如果改动的是两端,直接插入也可以。如果改的中间,那就是UUC => UCC(修改),那还不如这样:UUC => UUCC (插入)。所有的修改也都可以用插入代替。

  • 分析4

UCC 都找到后,如何找剩下的。我最先想到的是,用UCC将原字符串分割成多个字符串。这样剩下的就是一些“子问题”。但其实不是,因为剩下的串中一定没有完整的 UCC 。所以采用一个等长的新数组 v = [0] * len(s) 记录已组成 UCC 的字符。如果被用到了则 v[i] = 1

  • 分析5:

完整的UCC被找到后,那我们看两两的组合。在两两的组合(UUUCCUCC)中:只有UCCC是可利用的(只需一次操作)。匹配到则 count += 1 然后 m -= 1

  • 分析6: 剩下的无法利用的单个字符,只能使用2次添加操作才能让他们组成完整UCC。因此每有一个则count += 1 然后 m -= 2,注意手里如果不超过2次机会则直接 return

  • 分析7:

如果所有的字符都被用完了,而且手里还有超过3个操作次数。则 count += m // 3

代码

def solution(m: int, s: str) -> int:
    # PLEASE DO NOT MODIFY THE FUNCTION SIGNATURE
    # write code here
    n = len(s)
    v = [0] * n  # 定义访问数组
    count = 0

    # 统计UCC数量
    for i in range(n):
        if s[i: i + 3] == 'UCC':
            count += 1
            v[i: i + 3] = [1, 1, 1]

    # 统计UC或者CC数量
    for i in range(n):
        if m < 1:
            return count

        if v[i] == 1 or i + 1 < v and v[i+1] == 1:
            continue

        if (s[i: i + 2] == 'UC' or s[i: i + 2] == 'CC'):
            count += 1
            v[i: i+2] = [1, 1]
            m -= 1

    for i in range(n):
        if m < 2:
            return count

        if v[i] == 0:
            count += 1
            m -= 2

    return count + m // 3


if __name__ == '__main__':
    print(solution(m=11, s="UUUCCUUUUCCUUUCCU") == 8)
    print(solution(m=3, s="UCUUCCCCC") == 3)
    print(solution(m=6, s="U") == 2)
    print(solution(m=2, s="UCCUUU") == 2)

复杂度

  • 时间复杂度: O(n)

  • 空间复杂度: O(n)