编辑:
插入函数仅在递归函数使用空堆栈后才会执行。
START DELETE 0 [only one while loop executed]
START DELETE 1 [only one while loop executed]
START DELETE 2 [only one while loop executed]
START DELETE 3 [only one while loop executed]
START DELETE 4 [only one while loop executed]
START DELETE 5 [NO while loop executed because list is empty]
-------------------------
START INSERT iteration 4
END INSERT iteration 4
END DELETE 4
-------------------------
START INSERT iteration 3
END INSERT iteration 3
END DELETE 3
-------------------------
START INSERT iteration 2
END INSERT iteration 2
END DELETE 2
-------------------------
START INSERT iteration 1
END INSERT iteration 1
END DELETE 1
-------------------------
START INSERT iteration 0
END INSERT iteration 0
END DELETE 0
所以,我们首先运行插入函数 (4),因为当最后一个 delete_middle(5) 被执行时,列表堆栈是空的,并且它没有按照所述运行插入函数:
while len(stack)>0:
...........
insert(stack,temp,curr,n)
delete_middle 和n=5 中的上述内容将不会被执行,因为len(stack)==0。
中间是如何工作的:
#first executed delete_middle([2,4,1,18,34],5,0)
def delete_middle(stack,n,curr): iteration 1
while len(stack)>0: initial stack [2,4,1,18,34]
temp=stack.pop() stack after removal [2,4,1,18]
.....
delete_middle(stack,n,curr+1) -> becomes: delete_middle([2,4,1,18],5,1) iteration 2
while len(stack)>0: initial stack [2,4,1,18]
temp=stack.pop() stack after removal [2,4,1]
.....
delete_middle(stack,n,curr+1) > becomes: delete_middle([2,4,1],5,2) and so on until stack = [] (empty)
.....
(!) During these iterations insert(stack,temp,curr,n) is not executed because:
插入如何运行:
delete_middle([2,4,1,18,34],5,0)
# Iteration 1
#delete_middle(stack, n, curr+1)
delete_middle([2,4,1,18], 5, 1 )
insert not executed!
# Iteration 2
delete_middle([2,4,1],5,2)
insert not executed!
# Iteration 3
delete_middle([2,4],5,3)
insert not executed!
# Iteration 4
delete_middle([2],5,4)
insert not executed!
# Iteration 5
delete_middle([],5,5) # returns nothing because it does not enter the while loop
insert not executed!
Only from now -> each insert will be executed from inside delete_middle!
insert 4
insert 3
insert 2
insert 1
关于时间复杂度:
Time complexity = time taken to build the final list;
= (1 pop + 1 insert) * n
= O(n)
从最坏情况的角度来看,您可以说复杂度为 O(n),因为将列表大小减少 1 个元素涉及将 1 个元素附加到列表中,这是因为您只有 每级一次递归。(而..返回缩进)
虽然 pop 是 O(1) 并且列表每次都会减少 (O(log n)),但当每个 middle_delete 被调用时,您的算法的运行时间会随着输入数据的大小而增加执行 (n-1)总共附加;附加整个剩余列表。
Some starting point.
结束编辑
关于您的代码,是的,它可以工作,但如果我可以的话,会有一些限制:
- 目标列表的长度必须是奇数
- 需要一些额外的不必要的*标准 (
curr,n) [不必要的见
最后一部分]
- 函数未“完全正确”执行
解释:
自己试试
回答结束(请耐心等待:))
- 例如:
在您的代码中:
while len(stack)>0:
.....
return stack
基本上,您似乎返回了 while 循环的第一个值。
示例:
c = 0
def func(d):
while d < 5:
d+=1
return d
print(func(c))
递归效果是由None 在while 循环中产生的func(insert) 的巧妙使用触发的。这就像拉手断而不是踏板。 :)
关于您的问题:
如下所示,(中间函数执行+插入函数)为每个元素。
delete middle iterion 0
--------------------------
temp 34 0
delete middle iterion 1
--------------------------
temp 18 1
delete middle iterion 2
--------------------------
temp 1 2
delete middle iterion 3
--------------------------
temp 4 3
delete middle iterion 4
--------------------------
temp 2 4
delete middle iterion 5
--------------------------
======================
insert iteration 4
curr:4, stack:[], temp:2,n:5
======================
insert iteration 3
curr:3, stack:[2], temp:4,n:5
======================
insert iteration 2
curr:2, stack:[2, 4], temp:1,n:5
======================
insert iteration 1
curr:1, stack:[2, 4], temp:18,n:5
======================
insert iteration 0
curr:0, stack:[2, 4, 18], temp:34,n:5
[2, 4, 18, 34]
为什么我们在这里看不到 curr 的第一个值是 5?
如果你从 0 开始 (curr),你会看到从 4->0 的迭代,而当初始 curr 为 1 时,迭代将是 5->1;因此将触发 5 (N) 个删除函数调用。
- 我用一个简单的逻辑稍微重构了你的代码:
如果您有一个目标列表 [1,2,..,n-1,n] 并且您想使用递归函数删除中间部分,那么这种方法可能会吸引您:
让我们从 0 计数器开始count = 0
对于列表中的每个元素,计数器将增加 1 count+=1
现在,要从每一侧(左、右)消除一个元素以到达中间,我们可以说:如果 count 为 0 或 count 甚至从列表中删除最后一项,如果不是则删除第一项列表每次迭代都会丢失一项。
if count == 0 and count % 2 == 0:
target_list.pop(-1)
else:
target_list.pop(0)
如果列表有偶数个项目怎么办?然后我们也会包含这个场景:if len(target) == 2。
我还建议使用一个小技巧,即函数参数的默认值仅在定义函数时计算一次。
这是什么意思?检查Common Mistake #1 的示例。
将上面的所有内容都包含到最终的 func (O(N)) 中:
def eliminate_middle(target, count=0, beg_l=[],end_l=[]):
print(count) # O(N)
if len(target) == 1: # if target has only one element
return beg_l+sorted(end_l)
else:
if count == 0 or count % 2 == 0:
if len(target) == 2: # case len(target) is Even
return beg_l+sorted(end_l) #eliminates the two middle elements
end_l.append(target.pop(-1)) #target loses last element
return eliminate_middle(target,count+1)
else:
beg_l.append(target.pop(0)) # target loses first element
return eliminate_middle(target, count+1)
print(eliminate_middle([2,4,1,18,34]))