Как удалить только один максимум (мин) из списка, используя потоковый API Java 8 в O (N) времени и сложности O (C) пространства

2

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

public List<Integer> removeOneOfTheMax(List<Integer> nums) {
    int max = Integer.MIN_VALUE;
    int maxIndex = -1;
    Iterator<Integer> it = nums.iterator();
    for (int i = 0; it.hasNext(); i++) {
        Integer temp = it.next();
        if (max < temp) {
            maxIndex = i;
            max = temp;
        }

    }
    nums.remove(maxIndex);
    return nums;
}

1.. Что было бы эквивалентно методу, использующему API потока Java 8? Я хотел бы сохранить сложность времени и пространства, поэтому сортировка не разрешена.

2. На самом деле, если вы передадите LinkedList в код выше, сложность пространства будет O(C) (опять же, вне ввода), но насколько я понимаю .stream() создает дополнительную структуру данных, поэтому эквивалент потока API должен быть не менее O(n) в пространстве. Исправьте меня, если я ошибаюсь.

  • 2
    Почему вы думаете, что это « O(n) в космосе»? Поскольку уже существующий List не учитывается, требования к памяти, масштабируемые в зависимости от размера списка, отсутствуют. Это O(1) в пространстве, независимо от того, используете ли вы ArrayList или LinkedList . Это было бы иначе при использовании CopyOnWriteArrayList , но это не было бы ответственностью алгоритма.
  • 0
    Исключение элемента из ArrayList в худшем случае включает создание нового массива и повторное копирование всех элементов в него. Это не происходит в случае LinkedList.
Показать ещё 5 комментариев
Теги:
java-8
java-stream
max

1 ответ

3
Лучший ответ

Потоковое решение может выглядеть так:

int maxIndex = IntStream.range(1, nums.size()).reduce(0, (i, j) -> {
    int left = nums.get(i);
    int right = nums.get(j);
    return Integer.max(left, right) == left ? i : j;
});

nums.remove(maxIndex);

Под ним будет Spliterator.

Сама операция потока не собирается создавать дополнительные структуры данных.

  • 3
    Обычно рекомендуется использовать существующие методы, но здесь это только усложняет код. Все лямбда-выражения можно упростить до (i, j) -> nums.get(i)>=nums.get(j)? i : j
  • 0
    Это + ответ - это то, что я искал

Ещё вопросы

Сообщество Overcoder
Наверх
Меню