求解满足任意前缀中0的数量不少于1的数量的特定二进制字符串计数问题
求解满足任意前缀中0的数量不少于1的数量的特定二进制字符串计数问题
你提到的把0换成-1的思路其实已经摸到了关键解法的门槛,这个问题本质上是卡特兰数的经典应用场景,咱们一步步拆解来看:
首先,你的初始观察完全正确:这类字符串必须以0开头(不然第一个字符是1,直接违反“任意前缀0的数量≥1的数量”的要求),也必须以1结尾(因为总共有5个0和5个1,如果结尾是0,整个串的0数量会比1多1,不符合总数相等的条件)。
核心解法:反射原理 + 卡特兰数
咱们可以通过「总合法串数 = 所有可能的串数 - 不合格串数」的思路来计算:
- 计算所有可能的串数:长度为10、包含5个0和5个1的字符串总数,就是从10个位置中选5个放0(剩下的放1),对应的组合数是:
C(10,5) = 252 - 计算不合格串数:不合格串指的是存在某个前缀,1的数量超过0的数量的串。这里用反射原理来快速计算:
- 对于任意一个不合格串,找到第一个让1的数量比0多1的位置
k(也就是前k个字符里,1的数量 = 0的数量 + 1)。 - 把前
k个字符中的0和1互换(0变1,1变0),此时原来的5个0、5个1的串会变成6个0、4个1的串(因为前k个里原本1比0多1,互换后0比1多1,总0数增加1,1数减少1)。 - 反过来,每一个6个0、4个1的串都能对应回一个不合格的原串,所以不合格串的数量等于这类串的总数:
C(10,6) = C(10,4) = 210
- 对于任意一个不合格串,找到第一个让1的数量比0多1的位置
- 计算满足条件的串数:用总数减去不合格数,得到:
252 - 210 = 42
通用推广:卡特兰数公式
这个结果正好是第5个卡特兰数,对于更一般的情况——长度为2n、包含n个0和n个1,且任意前缀中0的数量≥1的数量的字符串,数量可以直接用卡特兰数公式计算:C(n) = (1/(n+1)) * C(2n, n)
比如当n=5时,代入得(1/6)*252=42,和咱们的计算结果一致。这个公式完全适用于更长的字符串,不用再像分情况枚举那样随着长度增加复杂度飙升,是非常高效的通用解法。
你之前尝试的分情况枚举思路其实也能得到结果,但对于更长的串来说,卡特兰数的方法显然更简洁实用。
备注:内容来源于stack exchange,提问作者Martin Westin
相关产品推荐
相关产品推荐

