В первом способе слишком много абстракций. Когда речь заходит о критической экономии памяти нужно сразу забывать про существовании Stream API, стараться не использовать autoboxing и пытаться эффективней использовать ресурсы. На то они и олимпиадные задачки, чтобы писать все сортировки руками вместо однострочных стримов и пр.
Что можно сделать:
- закрывать сканер после чтения (не закрыв он так и будет висеть у тебя в памяти, которой может не хватить допустим в середине алгоритма)
- открывать writer в самом конце (тоже самое что и со сканером, тем более что он тебе абсолютно не нужен в начале выполнения)
- заменить мапу на массив, убрать использование объекта Integer (со списком тоже желательно, но боттлнек твоего первого способа именно её использование, поэтому если заменишь правильно не сломав логику, то должно хватить.)
- не использовать стримы
По поводу подсчёта памяти сервером скорее всего просто запускают виртуалку с -Xmx16m параметром и реагируют на OutOfMemoryError, но это не точно.
ps Ты не можешь сравнивать Integer таким образом
a.getValue() != b.getValue()
. Integer суть объект, нужно использовать equals. А ещё в задании сказано разделять числа в output пробелами, а не переходами на новую строку, но это так, к слову.