Разбор задачи: Мешок с жетонами

Предложенный нами код:

 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:

  1. Уменьшаем силу на стоимость жетона: power -= tokens[l].
  2. Увеличиваем счет: score += 1.
  3. Сдвигаем левый указатель l вправо (l += 1), переходя к следующему жетону.

Шаг 5: Закрытие жетонов

elif score and l != r:
    power += tokens[r]
    score -= 1
    r -= 1

Если сила недостаточна для открытия текущего жетона, но у нас есть хотя бы одно очко (score > 0), мы можем закрыть жетон с конца массива:

  1. Увеличиваем силу на стоимость жетона: power += tokens[r].
  2. Уменьшаем счет на 1: score -= 1.
  3. Сдвигаем правый указатель 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.

Шаги цикла:

  1. power = 200, tokens[l] = 100. Открываем жетон:
    • power -= 100power = 100.
    • score += 1score = 1.
    • l += 1l = 1.
  2. power = 100, tokens[l] = 200. Силы недостаточно. Закрываем жетон:
    • power += 400power = 500.
    • score -= 1score = 0.
    • r -= 1r = 2.
  3. power = 500, tokens[l] = 200. Открываем жетон:
    • power -= 200power = 300.
    • score += 1score = 1.
    • l += 1l = 2.
  4. power = 300, tokens[l] = 300. Открываем жетон:
    • power -= 300power = 0.
    • score += 1score = 2.
    • l += 1l = 3.

Результат:

  • Максимальный счет: score = 2.

 



Вы должны Войти или Зарегистрироваться чтобы оставлять комментарии