最小化相邻 2 到 3 位的翻转以生成全 1 的二进制字符串
给定一个由0和1组成的二进制字符串S ,任务是找到生成全为 1 的二进制字符串所需的最小翻转次数。在两个或三个相邻索引上执行翻转。
例子:
Input: S = “0010”
Output: 2
Explanation: Operations performed are: 0010 -> 0001 -> 1111
Input: S = “0011110”
Output: 3
Explanation: Operations performed are: 0011110 -> 1111110 -> 1111000 -> 1111111
方法:解决这个问题的基本思路是对前2或3个字符进行翻转,并将递归结果与下一个位置相加。这只是所有可能性的递归暴力破解。对于字符串的每个索引,尝试两个相邻的翻转和三个相邻的翻转,然后在该子问题上递归。一件重要的事情是结果与翻转的顺序无关。
请按照以下步骤解决问题:
- 如果给定的字符串不包含任何零,则返回“0” ,如果只有“ 1 ”,则不需要翻转。
- 如果给定的字符串在任何时候都等于“ 00 ”或“ 000 ”,则返回“ 1 ”,因为只需翻转1次即可使其全部变为1 。
- 我们需要一个用于在递归调用的任何时刻存储和比较最小可能性的列表。
- 如果字符串以“ 0 ”开头并且字符串的长度大于2或3 ,那么我们翻转前两个或前三个字符并再次递归调用下一个索引。
- 如果字符串以“ 1 ”开头,我们会在其余部分递归调用它来删除它。
- 现在在“ 1 ”的情况下,如果“ 0 ”出现在前两个或三个位置,那么我们翻转前两个或三个位置并递归调用该部分的其余部分以及将结果附加/添加到列表中。
- 一旦一个循环完成,我们返回存储在列表中的所有元素中的最小值。
下面是上述方法的实现:
Python3
# Python program for the above approach
def minimumFlips(string):
# No flip needed
if "0" not in string:
return 0
# Flip the whole string at once
if string in ("00", "000"):
return 1
# Flip 1st 2 / 3 characters
def flip(n):
return string[:n]\
.translate({48: 49, 49: 48})\
+ string[n:]
# For tracking minimum flips
flips = [float('inf')]
# Flip if string starts with zero
if string.startswith("0"):
# Flip first 2 and call recursively
if len(string) > 2:
flips.append(1 + minimumFlips(flip(2)[1:]))
# Flip first 3 and call recursively
if len(string) > 3:
flips.append(1 + minimumFlips(flip(3)[1:]))
# If string starts with "1"
else:
# No flip + recursion
flips.append(minimumFlips(string[1:]))
# Flip if zero is at 2nd position
if "0" in string[:2]:
# Flip first 2 and call recursively
flips.append(1 + minimumFlips(flip(2)))
# Flip if zero is at 2nd position
if "0" in string[:3]:
# Flip first 3 and call recursively
flips.append(1 + minimumFlips(flip(3)))
return min(flips)
# Driver code
if __name__ == "__main__":
print(minimumFlips("0010"))
输出
2
时间复杂度:O(N!)
辅助空间:O(N)