Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Алгоритмы и структуры данных: продвинутый уровень Заправки


Выпуск 5. Заправки

Здравствуйте, ! Задача. Дано два массива A и B одинакового размера N, где N - это число заправок расположенных на пути. Дорога проходит через все заправки и закольцовывается (то есть по дороге мы можем объезать все заправки и вернуться в точку старта).

Массив A показывает, сколько топлива хранится на каждой заправке i.

У вас есть машина с беконечным баком. А в массиве B элемент i показывает, сколько топлива расходует ваша машина при переезде из точки i в i+1.

Нужно вернуть индекс i заправки, начиная с которой вы можете объехать все заправки, не оставшись без бензина по пути. Либо вернуть -1, если такого индекса не существует (с какой заправки не стратуй, всё равно останешься где-то без топлива).

Пример.
Дано:
    A =  [1, 2]
    B =  [2, 1]
Ответ: 1 (индекс в массивеб то есть мы стартуем со второй заправки)
Объяснение:
        Если вы стартуете с индекса 0, вы можете залить в бак A[0] = 1 
единиц топлива. Но вам нужно B[0] = 2 единицы топлива, чтобы доехать 
до заправки с индексом 1. 
        Если вы стартуете с заправки под индексом 1, вы можете залить в бак 
A[1] = 2 единицы топлива. И вам нужно B[1] = 1 топлива, чтобы доехать до 
заправки с индексом 0. И вы до неё доезжаете, и у вас ещё остаётся 1 единица 
топлива. Вы доливаете A[0] = 1 ещё одну единицу топлива, и у вас в баке 
становится 2 единицы топлива. В данной точке вам нужно B[0] = 2 единиц топлива,
чтобы доехать до заправки с номером 1 и завершить круг. 
Идея решения: прежде всего, можно просуммировать все значения требуемого топлива (из массива B) и вычесть из суммы все значения наличного топлива (массив А), чтобы понять, решаема ли задача в принципе. Но так мы не найдём нужный индекс, если задача решаема.

Поэтому идём по всем индексам от 0 до N и попарно вычитаем требуемое топливо из наличного (бензобак + заправка).

Компилируемое Java-решение

public class Solution {
    public int canCompleteCircuit(final List<Integer> gas, final List<Integer> cost) {
        // проверка на ноль
        if(gas == null || cost == null || gas.size() == 0 || cost.size() == 0 ||
           gas.size() != cost.size())
            return -1;
        int n = gas.size();
       
        int sumRemaining= 0;
        int total = 0;
        int start = 0;
       
        for(int i = 0; i < n; i++){
            // попарно вычитаем
            int remaining = gas.get(i) - cost.get(i);
            // если бак не ушёл в минус на предыдущем шаге
            if(sumRemaining >= 0)
            // то добавляем топливо заправки и вычитаем стоимость переезда в следующую точку
                sumRemaining += remaining;
            else{
// если бензобак ушёл в минус на предыдущем шаге, то мы начали не с той точки
// поэтому начинаем с текущей точки i, и заливаем remaining
                sumRemaining = remaining;
                start = i;
            }
// а вот тут подсчитываем, решаема ли задача в принципе.
// То, что было написано в идее решения сразу же
            total += remaining;
        }
// если задача в принципе решаема, то сумма элементов A минус сумма элементов B
// должна быть больше нуля, а необходимый индекс start - тот,
// который ни разу не "дискредитировал" себя
        if(total >= 0)
            return start;
        else return -1;  
    }
}

С уважением,
Наталия Македа
natalia.macheda at gmail.com
2021-03-17, Trento

Внимание!
Письмо, которое вы мне отправите с вопросами и коментариями по тематике данной рассылки, может быть опубликовано полностью или частично в данной рассылке, если в нём нет явного запрета на это.


© Наталия Македа 2021.
Все материалы рассылки защищены авторским правом. Любая перепечатка или использование материалов рассылки в коммерческих целях возможна лишь с письменного согласия автора. При некоммерческом использовании ссылка на выпуск обязательна.


В избранное