Я решал задачу для игры из двух стеков в ранге хакеров и застрял. Проблема в том, что мое решение не работает, когда количество стеков очень велико (миллионы записей)

https://www.hackerrank.com/challenges/game-of-two-stacks

Alexa имеет два стека неотрицательных целых чисел, стек A и стек B, где индекс 0 обозначает вершину стека. Алекса призывает Ника сыграть в следующую игру:

За каждый ход Ник может удалить одно целое число из вершины стека A или стека B.

Ник держит промежуточную сумму целых чисел, которые он удаляет из двух стеков.

Ник дисквалифицируется из игры, если в какой-то момент его беговая сумма становится больше некоторого целого числа X, указанного в начале игры.

Окончательная оценка Ника - это общее количество целых чисел, которые он удалил из двух стеков.

Найдите максимальное возможное количество очков, которое Ник может достичь (то есть максимальное количество целых чисел, которое он может удалить, не будучи дисквалифицированным) во время каждой игры, и напечатайте его в новой строке.

Для каждой игры выведите целое число в новой строке, обозначающее максимально возможное количество очков, которое Ник может набрать без дисквалификации.

Пример ввода 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
Nitesh 29 Май 2019 в 12:49

2 ответа

Лучший ответ

Начальные наблюдения:
а) Порядок, в котором Ник выбирает решение, не имеет значения. Если S = {a1, b1, a2, b2, ...}, вы можете изменить порядок и сначала выбрать всех из A, а затем B.

Б) Если у вас есть решение S = S_A + S_B, состоящее из элементов S_A элементов A и S_B элемента B. Вы можете перефразировать решение как «Некоторые элементы S_A из A» + «как можно больше элементов из B с учетом S_A» ,

Предлагаемый псевдокод:
1) Итерация по стеку А. Сохраните накопленную сумму.
2) Для каждого шага через A, проверьте, сколько элементов вы можете выбрать из B.

Оптимизация при необходимости: вы можете создать все накопительные суммы из B, и для каждого частичного решения из A выполнить двоичный поиск в этой таблице сумм, чтобы быстро определить, сколько элементов вы можете получить из B.

Вот реализация предложенной идеи, она решает проблему хакерранков, так что это своего рода обман для вас, если вы ее используете :-):

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)  
2
Christian Sloper 29 Май 2019 в 11:32

Я мог видеть, что вы не выходите из первоначального цикла for, как только вы выполнили критерии. Вы просматриваете весь список даже после того, как критерии выполнены, чего можно избежать. Попробуйте выйти из цикла, как только критерии будут выполнены.

 for i in range(len(a)):
        sum_list = sum_list + a[i]
        if sum_list <= x:
            a_list.append(a[i])
        else:
            break

Это определенно улучшит производительность в случае большого количества значений для списка а.

2
Krishna 29 Май 2019 в 10:29
56357697