Как сократить временные затраты на отгрузку товаров

Вопрос или проблема

У меня есть транспортное средство, которое имеет максимальную вместимость для перевозки предметов за одну поездку, и в каждой поездке оно может забрать максимальное количество предметов одного типа.

Пример: У меня есть массив предметов, где items[i] указывает количество предметов типа i.

items = [4,4,3]
вместимость транспортного средства за одну поездку = 3
максимальное количество предметов одного типа, разрешенное за одну поездку, составляет 3

вывод: 3

Ограничения:

n — размер массива предметов, 1 <= n <= 10^5

1 <= items[i] <= 10^5

1 <= вместимость <= 10^5

1 <= max_allowed_same_type <= 10^5

Вот мой код:

public static long solve(List<Integer> items, int capacity, int max_allowed_same_type) {
    PriorityQueue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder());
    pq.addAll(items);

    long result = 0;
    while (!pq.isEmpty()) {
        int load = 0;
        while (load < capacity && !pq.isEmpty()) {
            int item = pq.poll();
            int minItem = Math.min(max_allowed_same_type, item);
            int e = load + minItem;
            if (e > capacity) {
                int diff = capacity - load;
                pq.add(item - diff);
                break;
            } else {
                load += minItem;
            }
            if (item > minItem) {
                pq.add(item - minItem);
            }
        }
        result++;
    }
    return result;
}

public static void main(String[] args) {
    // Тест 1
    System.out.println(solve(Arrays.asList(4, 4, 3), 3, 3)); // 4

    // Тест 2
    System.out.println(solve(Arrays.asList(3, 2, 2, 6), 2, 1)); // 7

    // Тест 3 (тот, который не проходил)
    System.out.println(solve(Arrays.asList(1, 4), 1, 2)); // 5

}

Я не уверен, какова будет временная сложность этого кода. Я предполагаю, что временная сложность моего кода составляет O(sum(items)) в худшем случае, поправьте меня, если я ошибаюсь. Каков правильный подход для решения этой проблемы с меньшей временной сложностью.

Вы используете PriorityQueue, чтобы получить максимальный элемент на каждой итерации цикла. Это добавляет логарифмическую составляющую к вашей сложности, где n — размер кучи. Таким образом, сложность вашего алгоритма должна составлять O(s*log(n)), где s=sum(items). Однако, на мой взгляд, нет смысла использовать кучу. Вы можете просто пройтись по массиву предметов, уменьшая значение каждого предмета не более чем на max_items, чтобы получить общий вес нагрузки до вместимости.

Ответ или решение

Чтобы минимизировать количество поездок, необходимых для перевозки предметов, необходимо оптимально распределить загрузку транспортного средства с учетом его ограничений. Рассмотрим более эффективный способ решения этой задачи, который не требует использования очереди с приоритетом, и имеет меньшую временную сложность.

Анализ вашей текущей реализации

Вы используете очередь с приоритетом для получения максимального количества предметов на каждом шаге, что вносит дополнительную сложность в ваш код. Применяемый алгоритм фактически имеет временную сложность O(s * log(n)), где s — сумма всех предметов, а n — количество видов предметов.

Оптимизированный подход

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

  1. Рассмотрим каждый тип предмета.
  2. Загрузим максимальное количество предметов этого типа, учитывая ограничения.
  3. Продолжим до тех пор, пока все предметы не будут перевезены.

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

Пример реализации

Вот упрощенная версия вашего кода на Java:

public static long solve(List<Integer> items, int capacity, int max_allowed_same_type) {
    long trips = 0; // количество поездок

    for (int item : items) {
        while (item > 0) {
            trips++; // каждая итерация это поездка
            int load = 0; // текущая загрузка

            // Загружаем предметы данного типа, не превышая ограничения
            while (load < capacity && item > 0) {
                int toLoad = Math.min(max_allowed_same_type, item); // максимально допустимое количество для загрузки
                if (load + toLoad <= capacity) {
                    load += toLoad; // обновляем загрузку
                    item -= toLoad; // уменьшаем количество предметов данного типа
                } else {
                    int diff = capacity - load; // оставшееся свободное место
                    item -= diff; // корректируем количество оставшихся предметов
                    break; // при достижении полной загрузки выходим из цикла
                }
            }
        }
    }

    return trips;
}

public static void main(String[] args) {
    // Тестовые случаи
    System.out.println(solve(Arrays.asList(4, 4, 3), 3, 3)); // Ожидаемый вывод: 3
    System.out.println(solve(Arrays.asList(3, 2, 2, 6), 2, 1)); // Ожидаемый вывод: 7
    System.out.println(solve(Arrays.asList(1, 4), 1, 2)); // Ожидаемый вывод: 5
}

Вывод

Срезая использование очереди с приоритетом и вместо этого просто проходя по массиву предметов с учетом их количества и ограничений, вы можете значительно улучшить временную сложность вашего алгоритма. Теперь он работает с временной сложностью O(n), что делает его более эффективным для больших входных данных.

Таким образом, вместо O(s * log(n)), как в вашей первоначальной реализации, мы добились временной сложности O(n), что является идеальным решением для данной задачи.

Оцените материал
Добавить комментарий

Капча загружается...