Программа курса:
Разбор задачи: Мешок с жетонами
Предложенный нами код:
def bagOfTokensScore(tokens, power):
"""
:type tokens: List[int]
:type P: int
:rtype: int
"""
tokens.sort()
l, r, score = 0, len(tokens) - 1, 0
while l <= r:
if power >= tokens[l]:
power -= tokens[l]
score += 1
l += 1
elif score and l != r:
power += tokens[r]
score -= 1
r -= 1
else:
break
return scoreШаг 1: Сортировка жетонов
tokens.sort()
Перед началом работы жетоны сортируются по возрастанию их значений. Это делается для того, чтобы сначала пытаться открывать жетоны с наименьшей стоимостью (так как это требует меньше силы), а закрывать — с наибольшей стоимостью (чтобы максимально увеличить силу). Например, если tokens = [100, 200, 300], после сортировки массив остается в том же порядке.
Шаг 2: Инициализация переменных
l, r, score = 0, len(tokens) - 1, 0
lиr— указатели на начало и конец массиваtokens. Они используются для выбора жетонов:l— для открытия жетонов с минимальной стоимостью,r— для закрытия жетонов с максимальной стоимостью.score— текущий счет. Он изначально равен 0.
Шаг 3: Основной цикл
while l <= r:
Цикл продолжается, пока левый указатель l не пересечет правый указатель r. Это гарантирует, что все жетоны рассмотрены, и больше нет доступных действий.
Шаг 4: Открытие жетонов
if power >= tokens[l]:
power -= tokens[l]
score += 1
l += 1
Если текущая сила power больше или равна стоимости жетона, на который указывает l:
- Уменьшаем силу на стоимость жетона:
power -= tokens[l]. - Увеличиваем счет:
score += 1. - Сдвигаем левый указатель
lвправо (l += 1), переходя к следующему жетону.
Шаг 5: Закрытие жетонов
elif score and l != r:
power += tokens[r]
score -= 1
r -= 1
Если сила недостаточна для открытия текущего жетона, но у нас есть хотя бы одно очко (score > 0), мы можем закрыть жетон с конца массива:
- Увеличиваем силу на стоимость жетона:
power += tokens[r]. - Уменьшаем счет на 1:
score -= 1. - Сдвигаем правый указатель
rвлево (r -= 1), исключая этот жетон из дальнейшего рассмотрения.
Дополнительная проверка l != r гарантирует, что не произойдет закрытие одного и того же жетона, если указатели совпадают.
Шаг 6: Прерывание цикла
else:
break
Если:
- Силы недостаточно для открытия жетона, и
- Счет равен 0 (нет очков для закрытия жетона),
алгоритм завершает работу, так как больше нельзя предпринять никаких действий.
Шаг 7: Возврат результата
return score
После завершения цикла возвращается максимальный достигнутый счет.
Пример работы алгоритма
Рассмотрим пример:
tokens = [100, 200, 300, 400]
power = 200
Шаг 1: Сортировка
- После сортировки
tokens = [100, 200, 300, 400].
Шаг 2: Инициализация
l = 0,r = 3,score = 0.
Шаги цикла:
power = 200,tokens[l] = 100. Открываем жетон:power -= 100→power = 100.score += 1→score = 1.l += 1→l = 1.
power = 100,tokens[l] = 200. Силы недостаточно. Закрываем жетон:power += 400→power = 500.score -= 1→score = 0.r -= 1→r = 2.
power = 500,tokens[l] = 200. Открываем жетон:power -= 200→power = 300.score += 1→score = 1.l += 1→l = 2.
power = 300,tokens[l] = 300. Открываем жетон:power -= 300→power = 0.score += 1→score = 2.l += 1→l = 3.
Результат:
- Максимальный счет:
score = 2.