微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在给定列表中按该顺序查找 0,0,1 的简单方法

如何解决在给定列表中按该顺序查找 0,0,1 的简单方法

我正在尝试编写一个简单的函数来查找列表中是否按该顺序出现 0,1。
它应该返回 TrueFalse

列表可以包含任意数量的数字。
对于函数 ZeroZeroOne 示例如下:

>> ZeroZeroOne( [0,1] )
>> True

>> ZeroZeroOne( [1,0] )
>> False

# there are 2s in between but the following does have 0,1 occurring and in correct order 
>> ZeroZeroOne( [0,2,1] )
>> True

我有这个功能

def ZeroZeroOne(nums):
      
    FoundIt = False

    #quick return if defo not possible
    if (nums.count(0) < 2) and (nums.count(1) == 0):
        return FoundIt

    n = len(nums)
    for x in range(n-2):
        if nums[x] == 0:
            for i,z in enumerate(nums[(x+1):]):
                if z==0 and z!=1:
                    for j,q in enumerate(nums[(i+1):]):
                        if q==1 and q!=0:
                            FoundIt=True

    return FoundIt

为什么函数为这个列表 [0,1,1] 返回 True?

此外....
对于一个看似简单的问题,这个函数似乎过于复杂。

解决方法

您可以简单地修改 this answer 中的有序子序列测试以获得优雅的解决方案:

def ZeroZeroOne(arr):
    test = iter(a for a in arr if a in (0,1))
    return all(z in test for z in (0,1))

我现在意识到你不想接受 0,1 0,1。


您可以使用 itertools.tee 检查匹配项:

def ZeroZeroOne(arr):
    e = itertools.tee((a for a in arr if a in (0,1)),3)
    # move second iterator forward one
    next(e[1])
    # move third iterator forward two
    next(e[2])
    next(e[2])
    return (0,1) in zip(*e)

在这种情况下使用 tee 的好处是它有效地为您维护了最后三个元素的滚动缓冲区。你不需要制作一个新的切片或循环索引它之类的东西。


只是为了好玩,这里有一个更通用的纯 python 解决方案。它接受 arrtemplate 的任何迭代:

def contains_template(arr,template):
    template = tuple(template)
    unique = set(template)
    filtered = (a for a in arr if a in unique)
    e = itertools.tee(filtered,len(template))
    for n,it in enumerate(e):
        for _ in range(n):
            next(it)
    return template in zip(*e)

虽然 itertools.tee 是维护滚动缓冲区的好方法,但您可以使用列表(或更有效地,collections.deque)来实现相同的功能:

def contains_template(arr,template):
    template = list(template)
    unique = set(template)
    filtered = (a for a in arr if a in unique)
    buffer = [next(filtered) for _ in range(len(template) - 1)]
    buffer.insert(0,None)
    for e in filtered:
        buffer.pop(0)
        buffer.append(e)
        if template == buffer:
            return True
    return False

最后,这是一个非常简单的解决方案,没有滚动缓冲区:

def contains_template(arr,template):
    template = list(template)
    n = len(template)
    unique = set(template)
    filtered = [a for a in arr if a in unique]
    return any(filtered[i:i + n] == template for i in range(len(filtered) - n))
,

您也可以使用递归函数来实现:

def check(seq,liste,i=0,j=0):
    if i >= len(seq):
        return True
    if j >= len(liste):
        return False
    if seq[i] == liste[j]:
        return check(seq,i + 1,j + 1)
    elif liste[j] in seq:
        # look for the last index you can restart from
        for k in range(i - 1,-1,-1):
            if seq[k] == liste[j]:
                if seq[:k] == seq[i - k:i]:
                    ind = k
                    break
        else:
            ind = 0
        return check(seq,ind,j + (not i))
    else:
        return check(seq,i,j + 1)



# seq = [0,1] for ZeroZeroOne
print(check([0,1],[0,1]))  # True
print(check([0,200,101,2,4,5,3,1]))  # False
,

我认为这可以满足您的要求:)

def ZeroZeroOne(arr):
    dropped = [x for x in arr if x==0 or x==1]
    slices = [dropped[i:i+3] for i in range(len(dropped)-2)]
    if [0,1] in slices: return True
    else: return False
,

您可以通过一个循环来实现这一点 - O(n) 时间复杂度。因为它是针对这种特定情况的。试试下面的代码。

def ZeroZeroOne(nums):
    found_pattern = []
    for num in nums:
        if num == 1:
            found_pattern.append(1)
            if len(found_pattern) == 3:
                return True
            else:
                found_pattern = []
        elif num == 0 and len(found_pattern) < 2:
            found_pattern.append(0)
    return False


print(ZeroZeroOne([0,1]))
print(ZeroZeroOne([0,1,1]))

但我认为如果需要,您也可以概括这一点。如果您需要通用方法,您可能需要查看 grep 的工作原理并针对您的用例修改它。

,
def ZeroZeroOne(nums):
    filtered_nums = [x for x in nums if x in [0,1]]
    return '*'.join([str(x) for x in [0,1]) in '*'.join([str(x) for x in filtered_nums])

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。