我正在尝试Hackerrank的相同堆栈问题:https://www.hackerrank.com/challenges/equal-stacks/problem。
有人可以帮我理解下面两个代码逻辑的区别。虽然第一个失败了,另一个却成功了:
首先(我的解决方案):
n1, n2, n3 = map(int, input().split())
H1 = list(map(int, input().split()))
H2 = list(map(int, input().split()))
H3 = list(map(int, input().split()))
sum_h1 = sum(H1)
sum_h2 = sum(H2)
sum_h3 = sum(H3)
#print (sum_h1,sum_h2,sum_h3)
while not (sum_h1 == sum_h2 and sum_h2 == sum_h3):
if sum_h1 > sum_h2 or sum_h1 > sum_h3:
#t = H1.pop()
sum_h1 -= H1[0]
#print ("Checking:",sum_h1)
if sum_h2 > sum_h1 or sum_h2 > sum_h3:
#t = H2.pop()
sum_h2 -= H2[0]
if sum_h3 > sum_h1 or sum_h3 > sum_h2:
#t = H3.pop()
sum_h3 -= H3[0]
print (sum_h1)
第二种解决方案(正确):
n1, n2, n3 = map(int, input().split())
H1 = list(map(int, input().split()))[::-1]
H2 = list(map(int, input().split()))[::-1]
H3 = list(map(int, input().split()))[::-1]
sum_h1 = sum(H1)
sum_h2 = sum(H2)
sum_h3 = sum(H3)
#print (sum_h1,sum_h2,sum_h3)
while not (sum_h1 == sum_h2 and sum_h2 == sum_h3):
if sum_h1 > sum_h2 or sum_h1 > sum_h3:
t = H1.pop()
sum_h1 -= t
if sum_h2 > sum_h1 or sum_h2 > sum_h3:
t = H2.pop()
sum_h2 -= t
if sum_h3 > sum_h1 or sum_h3 > sum_h2:
t = H3.pop()
sum_h3 -= t
print (sum_h1)
我知道在第二个中我们正在反转输入数组。但是,这应该有所不同。
我完全不解。
请帮我指出第一段代码的问题。
提前致谢。
答案 0 :(得分:2)
我知道在第二个中我们正在反转输入数组。但是,这应该有所不同。
是 有所作为。假设你有以下堆栈:
1
1 2 1
1 1 3
现在我们可以简单地从右侧堆栈中弹出1
(粗体字),并且所有堆栈都具有相同的高度。
但相反的是不是真的。如果堆栈相反:
1
1 1 3
1 2 1
我们必须弹出正确的堆栈,因为它是最大的堆栈。但我们只能从中弹出3
(粗体字)。因此,最大高度只能是1
。当我们弹出3
时,我们稍后会发现,我们可以获得的最大等高是0
。如果我们弹出正确的堆栈,我们获得:
1
1 1
1 2 1
但是中间的筹码底部有一个2。所以我们永远不能在中间产生1作为堆栈的总和。
堆栈意味着订单:在我们可以弹出该元素之前,我们必须删除圆柱体上方的元素,因此顺序很重要。
在第一个代码片段中,从该堆栈的总和中减去第一个元素。但是您从列表中不删除该元素。因此,您不断从堆栈中弹出第一个元素。
你可以通过pop(0)
(从列表的开头弹出)或稍后删除该元素来修复它:
# fix of the first code fragment
while not (sum_h1 == sum_h2 and sum_h2 == sum_h3):
if sum_h1 > sum_h2 or sum_h1 > sum_h3:
sum_h1 -= H1.pop(0)
#print ("Checking:",sum_h1)
if sum_h2 > sum_h1 or sum_h2 > sum_h3:
sum_h2 -= H2.pop(0)
if sum_h3 > sum_h1 or sum_h3 > sum_h2:
sum_h3 -= H3.pop(0)
或者:
# fix of the first code fragment
while not (sum_h1 == sum_h2 and sum_h2 == sum_h3):
if sum_h1 > sum_h2 or sum_h1 > sum_h3:
sum_h1 -= H1[0]
del H1[0]
#print ("Checking:",sum_h1)
if sum_h2 > sum_h1 or sum_h2 > sum_h3:
sum_h2 -= H2[0]
del H2[0]
if sum_h3 > sum_h1 or sum_h3 > sum_h2:
sum_h3 -= H3[0]
del H3[0]
但请注意,这些效率低下:从一开始就弹出一个 O(n)操作, n 列表的大小。
答案 1 :(得分:2)
由于@Willem Van Onsem和@coldspeed解释了第一个解决方案与另一个解决方案有何不同,我认为我可以解释一个更容易理解的类似解决方案(我认为)。
比方说,堆栈与原始问题相同:
3 2 1 1 1 (stack1)
4 3 2 (stack2)
1 1 4 1 (stack3)
在这里,最左边的数字是每个堆栈的顶部,最右边的是底部。我选择第一个堆栈作为参考堆栈(但可以是三个堆栈中的任何一个)。卸下气瓶时其可能的高度为8, 5, 3, 2, 1, 0
。任务是尝试所有的高度,看看它们是否可能是常见的。然后,最大共同高度就是答案。
让我们从下至上解决问题。因此,堆栈是空的,我们希望从头开始构建它们。在构建它们时,我们会找到高度相等的所有堆栈配置。因此,具有最大高度的配置将是该问题的答案。
每个堆栈的初始最大公共高度以及当前高度为0
0
0
0
0 (max)
在1
的高度上加上stack1
。然后,由于stack2
的当前高度小于stack1
的当前高度,因此请通过累加底部元素来增加其高度。对stack3
1
2
1
0 (max)
由于高度不同,最大残留量0
。因此,1
不能成为堆栈的常见高度。
在1
的高度上加上stack1
。 stack2
的高度相等,因此请勿执行任何操作。对于stack3
,只要高度减小,就不断求和。
2
2
5
0 (max)
3
5
5
0 (max)
3
5
5
0 (max)
5
5
5
5 (max)
8
9
10
5 (max)
在第一个堆栈为空时输出最大高度,并且与其他堆栈(如果它们仍然是非空的)一起工作是没有意义的。
5 (max)
现在,算法本身(为简便起见,在Python3
中:
n, m, k = map(int, input().split())
stack1 = list(map(int, input().split()))
stack2 = list(map(int, input().split()))
stack3 = list(map(int, input().split()))
max_height = 0
height1 = 0
height2 = 0
height3 = 0
while len(stack1) > 0:
if len(stack1) > 0:
height1 += stack1.pop()
while len(stack2) > 0 and height2 < height1:
height2 += stack2.pop()
while len(stack3) > 0 and height3 < height1:
height3 += stack3.pop()
if height1 == height2 == height3:
max_height = height1
print (max_height)
答案 2 :(得分:1)
您的解决方案与正确的解决方案之间的区别在于您的堆栈是相反的。在这种情况下,您应该调用list.pop(0)
来删除第一个元素。
while not (sum_h1 == sum_h2 and sum_h2 == sum_h3):
if sum_h1 > sum_h2 or sum_h1 > sum_h3:
t = H1.pop(0) # -------------- pop 0th element
sum_h1 -= t
if sum_h2 > sum_h1 or sum_h2 > sum_h3:
t = H2.pop(0) # -------------- pop 0th element
sum_h2 -= t
if sum_h3 > sum_h1 or sum_h3 > sum_h2:
t = H3.pop(0) # -------------- pop 0th element
sum_h3 -= t
print (sum_h1)
对于此输入:
5 3 4
3 2 1 1 1
4 3 2
1 1 4 1
这是输出:
5