📅  最后修改于: 2023-12-03 15:36:57.231000             🧑  作者: Mango
在编程中,有一种经典的问题就是如何在一个数组中删除顺序先于插入顺序的元素。
给定一个长度为 $n$ 的数组 $a$,元素初始都为 $0$。 现在进行若干次操作,每次操作可以是:
删除数组中最左侧(下标为 $0$)且值为 $0$ 的元素(如果有的话)。
在数组中最右侧插入元素。
然后问题就是,给定 $m$ 次操作后数组中值为 $0$ 的元素数量。
以下是一些例子:
n = 10, m = 5
操作序列为:['I', 'D', 'I', 'I', 'D']
初始数组:[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
操作后: [0, 0, 0, 0, 0]
n = 20, m = 10
操作序列为:['I', 'I', 'D', 'I', 'I', 'I', 'D', 'D', 'D', 'D']
初始数组:[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
操作后: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
我们可以用一个列表 res
来表示末尾插入的元素,每次插入一个元素时,把该元素插入列表尾部;每次删除操作时,从列表头部开始,遍历并删除所有为 $0$ 的元素。
def del_insert(n: int, m: int, ops: List[str]) -> int:
res = []
for op in ops:
if op == 'I':
res.append(1)
else:
for i in range(len(res)):
if res[i] == 0:
res[i], res[i+1:] = res[-1], res[i+1:]
res.pop()
break
return len(res) - res.count(0)
时间复杂度:$O(m \cdot n)$。
我们也可以用两个栈 inStack
和 outStack
来实现。每次插入一个元素时,把该元素插入 inStack
中;每次删除操作时,如果 outStack
栈顶不为 $0$,删除 outStack
栈顶元素;否则,将 inStack
的元素依次出栈并插入 outStack
中,直到找到第一个不为 $0$ 的元素并删除。
def del_insert(n: int, m: int, ops: List[str]) -> int:
inStack, outStack = [], []
for op in ops:
if op == 'I':
inStack.append(1)
else:
if outStack:
outStack.pop()
else:
while inStack:
outStack.append(inStack.pop())
if outStack:
outStack.pop()
return len(inStack) + len(outStack)
时间复杂度:$O(m)$。
本篇介绍了两种解决顺序先删除再插入的元素计数的方法,一个是暴力模拟,一个是使用两个栈。根据需求不同,可以选择不同的方法进行实现。