Size: a a a

2020 August 11

DC

Denis Chikanov in learn.java
Gukov Viktor
Как можно оценивать сложность алгоритмов которые используют стримы?
Допустим есть простая задача:
Дан массив чисел, в нем все числа повторяются кроме одного. Найдите это число

Я могу решить его обычным циклом for, используя подсчет через мапу, сложность будет очевидно O(N)

Или же я могу решить это стримом через мапу, например:
Arrays.stream(arr)
               .boxed()
               .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
               .entrySet().stream()
               .filter(entry -> entry.getValue() == 1)
               .mapToInt(Map.Entry::getKey)
               .findFirst()
               .getAsInt();


Но тут встает проблема во внутренней реализации библиотек, например Collectors, и то, что стримы по сути своей ленивы.
Всегда ли O сложность стрима будет равна линейному аналогу?
У этой штуки кстати правильное решение какое-то другое, я не помню, но оно должно есть константу по памяти
источник

GV

Gukov Viktor in learn.java
Denis Chikanov
У этой штуки кстати правильное решение какое-то другое, я не помню, но оно должно есть константу по памяти
XOR-ом считать. Единственное число которое себе биты не свопнет
источник

DC

Denis Chikanov in learn.java
Угу.
источник

A

Anton in learn.java
Denis Chikanov
А ещё в твоём случае надо не забыть обработать минус (который не цифра, если что)
Да, но 1 раз, в твоём случае минус от каждого числа отрезать
источник

GV

Gukov Viktor in learn.java
Denis Chikanov
Ну внутренняя реализация библиотек имеет какую-то асимптотическую сложность, да, не знать её ты можешь и для не-стримов
То есть микробенчи наше всё? В теории если сойдутся два мнения в виде скорость линейных циклов vs ленивость стримов, теорией тут никак не доказать
источник

DC

Denis Chikanov in learn.java
Anton
Да, но 1 раз, в твоём случае минус от каждого числа отрезать
На самом деле если уж припёрло, в обоих случаях проще Math.abs на инпуте вызвать.
источник

DC

Denis Chikanov in learn.java
Gukov Viktor
То есть микробенчи наше всё? В теории если сойдутся два мнения в виде скорость линейных циклов vs ленивость стримов, теорией тут никак не доказать
Ленивость на асимптотической сложности не сказывается ровно никак
источник

A

Anton in learn.java
Denis Chikanov
На самом деле если уж припёрло, в обоих случаях проще Math.abs на инпуте вызвать.
Тогда уж проще тупо старший бит обнулить)
источник

NG

Nikita Gryzlov in learn.java
Denis Chikanov
Ленивость на асимптотической сложности не сказывается ровно никак
разве быстрый выход не приблизит сложность к логарифму?
источник

DC

Denis Chikanov in learn.java
Nikita Gryzlov
разве быстрый выход не приблизит сложность к логарифму?
С чего бы вдруг?
Ну то есть константа может поменяться, но асимптотическая сложность от этого не изменится.
источник

MO

Max Olsson in learn.java
Gukov Viktor
Как можно оценивать сложность алгоритмов которые используют стримы?
Допустим есть простая задача:
Дан массив чисел, в нем все числа повторяются кроме одного. Найдите это число

Я могу решить его обычным циклом for, используя подсчет через мапу, сложность будет очевидно O(N)

Или же я могу решить это стримом через мапу, например:
Arrays.stream(arr)
               .boxed()
               .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
               .entrySet().stream()
               .filter(entry -> entry.getValue() == 1)
               .mapToInt(Map.Entry::getKey)
               .findFirst()
               .getAsInt();


Но тут встает проблема во внутренней реализации библиотек, например Collectors, и то, что стримы по сути своей ленивы.
Всегда ли O сложность стрима будет равна линейному аналогу?
А почему нельзя просто найти первый попавшийся элемент, отличный от первого элемента массива?

Апд: да, точно, надо подсчитать же
источник

M

Mamoka in learn.java
Спасибо всем большое за ответ про числа
источник

A

Anton in learn.java
Denis Chikanov
У этой штуки кстати правильное решение какое-то другое, я не помню, но оно должно есть константу по памяти
источник

DC

Denis Chikanov in learn.java
>за константу памяти
>скидываешь решение с хэшмапом

Ну ты издеваешься, не иначе.
источник

DC

Denis Chikanov in learn.java
Там уже даже выше сам вопрошающий написал, как.
источник

A

Anton in learn.java
Denis Chikanov
>за константу памяти
>скидываешь решение с хэшмапом

Ну ты издеваешься, не иначе.
Нет, затупил, извини
источник

MO

Max Olsson in learn.java
  OptionalInt get(int... arr) {
   return IntStream
       .range(1, arr.length)
       .filter(i -> arr[i] != arr[0])
       .map(i -> (i < arr.length - 1 && arr[i] == arr[i + 1]) ? arr[0] : arr[i])
       .findFirst();
 }
источник

DC

Denis Chikanov in learn.java
Max Olsson
  OptionalInt get(int... arr) {
   return IntStream
       .range(1, arr.length)
       .filter(i -> arr[i] != arr[0])
       .map(i -> (i < arr.length - 1 && arr[i] == arr[i + 1]) ? arr[0] : arr[i])
       .findFirst();
 }
Что, где, зачем
источник

MO

Max Olsson in learn.java
Denis Chikanov
Что, где, зачем
А чем плохо?
источник

DC

Denis Chikanov in learn.java
Max Olsson
А чем плохо?
Ну, например, тем, что оно не работает (и главное непонятно, как должно работать).
источник