如何解决在给定列表中按该顺序查找 0,0,1 的简单方法
我正在尝试编写一个简单的函数来查找列表中是否按该顺序出现 0,1。
它应该返回 True
或 False
。
列表可以包含任意数量的数字。
对于函数 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 解决方案。它接受 arr
和 template
的任何迭代:
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 举报,一经查实,本站将立刻删除。