二进制字符串是一个字符串,其中每个字符都是“0”或“1”。二进制字符串S是好的,当且仅当对于S的每个子字符串时,'0'的数量小于或等于'1的数字。
字符串S的子字符串可以通过从S的开头删除几个(或零)字符和从S的结尾删除几个(或零)字符来获得,从S中留下至少两个字符。例如,如果S =“abcdfab”,然后“abcd”,“fab”,“bcdfa”,“abcdfab”是S的子串,而“abab”,“”,“d”和“adcdab”不是S的子串。
我试图找出一种检查长度为N的二进制字符串是否良好的方法。
天真的方法是检查这个二进制字符串的每个子字符串,其时间复杂度为O(N ^ 2),是否存在一个时间复杂度为O(N)或更好的算法?
答案 0 :(得分:5)
为了使每个单个(两个或多个字符)子字符串至少具有与零一样多的子字符串,可以没有连续的零 - 事实上,您至少需要两个每对零之间的一个。这是因为字符串010
无效,但没有 0110
的双字符子字符串违反了您的约束。
所以算法是:
set oneCount to 2 # Zero at start of string is okay.
for each character ch in string:
if ch is 0:
if oneCount is less than 2:
generate error
set oneCount to 0
else:
increment oneCount
实际上是O(n)时间,但实际上你可以通过分摊成本来做得更好。由于在检查之前字符串可能有多个修改操作,因此您可以推迟检查以降低摊销成本。
通过这个,我的意思是缓存字符串的有效性,这样,如果你在没有修改它的情况下进行检查,只需返回缓存的值而不是重新检查。这是最粗糙的摊销水平,但可能会导致自身的改善:
define string = "", dirty = false, cachedValidity = true
define isValid():
if dirty:
cachedValidity = true
set oneCount to 2
for each character ch in string:
if ch is 0:
if oneCount is less than 2:
cachedValidity = false
exit for loop
set oneCount to 0
else:
increment oneCount
dirty = false
return cachedValidity
然后你必须确保字符串上的任何操作都将dirty
设置为true,这在面向对象的语言中实际上非常容易。
要进行更多优化,您不需要为所有操作设置dirty
为真,这实际上取决于您正在做什么。字符串有效性在(至少)以下条件下不会改变:
这些操作都不会影响有效性,因此不应设置dirty
标志。您可以在分析中发现其他人,但这是一个良好的开端,可以让您进一步分摊检查费用。
答案 1 :(得分:2)
每对0应该至少有两个1。它开着)。
def isGood(bstr):
count = 2
for i in bstr:
if i == '0':
if count >= 2:
count = 0
else:
return False
else:
count += 1
return True
print(isGood("0010101"))
希望这会有所帮助。