试图找到一个更有效的算法

时间:2017-11-07 01:38:12

标签: string algorithm performance time-complexity

二进制字符串是一个字符串,其中每个字符都是“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)或更好的算法?

2 个答案:

答案 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为真,这实际上取决于您正在做什么。字符串有效性在(至少)以下条件下不会改变:

  1. 如果您在另一个旁边插入一个。
  2. 如果您删除了另一个之间的那个。
  3. 如果你连续四次在中间插入一个零。
  4. 这些操作都不会影响有效性,因此不应设置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"))

希望这会有所帮助。