2017-01-27 8 views
2

Вот код для удаления только одного из максимальных значений (в этом случае первый, но это не имеет значения) из списка. Это O(n) во времени и O(n) в пространстве (за пределами ввода).Как удалить только один макс (мин) из списка с использованием API-интерфейса Java 8 в O (N) времени и сложности пространства O (C)

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. Что бы эквивалент метода с использованием Java 8 потока API? Я хотел бы сохранить сложность времени и пространства, поэтому сортировка не допускается.

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

+2

Почему вы думаете, что это «O (n)« в пространстве »? Поскольку уже существующий 'List' не учитывается, нет требования к памяти, которое масштабируется с размером списка. Это 'O (1)' в пространстве, независимо от того, используете ли вы 'ArrayList' или' LinkedList'. Это будет отличаться при использовании 'CopyOnWriteArrayList', но это не будет ответственность алгоритма. – Holger

+0

Устранение элемента из массива ArrayList в худшем случае связано с созданием нового массива и повторением всех элементов. Этого не происходит в случае LinkedList. – GA1

+2

'ArrayList.remove (int)' [никогда не делает этого] (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/ArrayList.java # 491). Возможно, вы сбиваете с толку 'add'. Однако, даже если это было так дорого, это не было свойством вашего алгоритма. – Holger

ответ

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); 

Под там будет Spliterrator.

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

+2

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

+0

Это + ответ, что я искал – GA1

Смежные вопросы