我正在为Hackers rank上的两堆游戏解决问题并陷入困境。 问题是当堆栈数非常大(数百万个条目)时,我的解决方案无法正常工作
https://www.hackerrank.com/challenges/game-of-two-stacks
Alexa有两个非负整数堆栈,堆栈A和堆栈B,其中索引0表示堆栈的顶部。 Alexa挑战Nick玩以下游戏:
在每一步中,Nick都可以从A或B堆栈的顶部删除一个整数。
Nick保持了从两个堆栈中删除的整数的连续总和。
如果尼克的总和在任何时候都大于比赛开始时给定的某个整数X,那么他将被取消比赛资格。
Nick的最终分数是他从两个堆栈中删除的整数总数。
在每场比赛中找出Nick可以获得的最高得分(即,他可以删除而不被取消资格的最大整数数),并将其打印在新的一行上。
对于每场比赛,在新行上打印一个整数,表示尼克在不被取消资格的情况下所能获得的最大得分。
样本输入0
1 -> Number of games
10 -> sum should not exceed 10
4 2 4 6 1 -> Stack A
2 1 8 5 -> Stack B
样本输出
4
下面是我的解决方法
def twoStacks(x, a, b):
a_list = []
sum_list = 0
for i in range(len(a)):
sum_list = sum_list + a[i]
if sum_list <= x:
a_list.append(a[i])
else:
break
print(a_list)
print(a[i])
print(sum_list)
max_first = len(a_list)
replacement_list = []
list_a_length = len(a_list)
list_replacement_length = len(replacement_list)
list_b_length = len(b)
replacement_list_sum = 0
a_list_sum = sum(a_list)
while True:
max_first = max(max_first, list_a_length + list_replacement_length)
#print("max final is ",max_first)
#print(sum(replacement_list))
#print(sum(a_list))
#print(b[0])
#print(type(replacement_list), type(a_list), type(b))
#print("sum of a lis is", sum(a_list))
if list_b_length == 0:
break
elif replacement_list_sum + a_list_sum + b[0] <= x:
#print(b[0])
replacement_list_sum = replacement_list_sum + b[0]
replacement_list.append(b.pop(0))
list_replacement_length += 1
list_b_length -= 1
if replacement_list_sum > x:
break
elif a_list:
a_list_sum = a_list_sum - a_list[-1]
a_list.pop()
list_a_length -= 1
#print(a_list)
else:
break
# print(replacement_list)
# print(a_list)
return max_first
其中a是第一个堆栈,b是第二个堆栈,x是(1000000000)范围内的和
问题是我的代码给出了正确的结果,但是对于大量代码,需要很长时间才能给出输出。任何更好的解决方案都值得赞赏
编辑:
我更改了密码,但仍然花了很多时间
答案 0 :(得分:2)
我看到一旦满足条件,您就不会退出初始for循环。即使符合条件,您也要遍历整个列表,这可以避免。 符合条件后,尝试打破循环。
for i in range(len(a)):
sum_list = sum_list + a[i]
if sum_list <= x:
a_list.append(a[i])
else:
break
如果列表a的值很多,这肯定会提高性能。
答案 1 :(得分:2)
初步观察:
a)尼克选择解决方案的顺序无关紧要。如果S = {a1,b1,a2,b2,...},可以重新排序并从A中首先选择所有人,然后选择B。
b)如果有一个解决方案S = S_A + S_B,由A的S_A元素和B的S_B元素组成。您可以将解决方案改写为“ B中的某些元素S_A” +“尽可能多的元素给定S_A“。
建议的伪代码:
1)遍历堆栈A。保留累积和。
2)对于通过A的每个步骤,请检查您可以从B中选择多少个元素。
必要时进行优化: 您可以从B创建所有累加的总和,并针对A的每个部分解决方案在此总和表上进行二进制搜索,以快速确定可以从B抓取多少个元素。
这里是建议思想的实现,它解决了hackerrank问题,因此,如果使用它,它有点欺骗您:-):
from itertools import accumulate
import bisect
def twoStacks(x,a,b):
cum_sum_b = list(accumulate(b))
cum_sum_a = [0]+list(accumulate(a))
return max( bisect.bisect_right(cum_sum_b, x-a_sum ) +i for i, a_sum in enumerate(cum_sum_a) if a_sum <= x)