Всем привет!
Я продолжаю изучать Яву, и это дается не очень легко. Новая проблема встала при написании задач на теорию графов.
Если на Си++ я использовал вектора, то тут работа с Vector несколько иная, а LinkedList и ArrayList довольно медленны и занимают очень много памяти.
Что вы предпочитаете? Или при ограничениях до 2000^2 ребер и 64 Мб памяти надо всегда писать все руками?
Извиняюсь, но вопрос какой-то нетолковый. Что значит "довольно медленны" и что значит "очень много". Что значит 64Мб - хипа или всего?
Они конечно медленнее чем простой массив в Си, но не настолько медленнее, как можно было бы опасаться. Вообще говоря довольно шустрые. %)
Что значит "писать руками" - в смысле массив руками написать вместо ArrayList или что?
ArrayList и LinkedList кроме того очень разные структуры - в первом доступ к центральным элементам за O(1), во втором за O(N) - с другой стороны при операциях стека/очереди первый будет работать несколько медленнее. Так что их надо правильно выбирать.
Вообще потребность в ArrayList в спортивных задачах обычно невелика т.к. почти всегда вместо него простой массив можно забацать.
В некоторых случаях удобно использовать вместо массива HashMap с ключом по индексу.
UPD: И поясните, что вы с 4млн рёбер своими делать собрались? Если вам нужен 1 проход по ним, то тут даже "довольно медленные" ArrayList/LinkedList справятся. Но в какой задаче нужен 1 проход по всем рёбрам, и чтобы их при этом ещё хранить было зачем-то нужно...
Как-то так можно исправить, хотя это не очень симпатично выглядит. Допускает ли задача вообще другое решение - не знаю, не вчитывался.
Но на тимусе точно есть задачи в которых java-решение нереально или почти нереально затолкнуть по времени/памяти - из тех что натыкался, помню, была 1100... Или путаю...
> при операциях стека/очереди первый будет работать несколько медленнее
При операциях стека ArrayList будет работать в целом куда быстрее связанного списка.
Кстати... Прав!!! Но заметим - только если "верхушка" стека в конце. Если в начале, то ой-ой... ;-)
UPD:
Я имею в виду, если делать:
list.add(0, elem);
elem = list.remove(0);
То быстрее LinkedList (в десятки раз, если сначала заполнить потом вытряхивать)
А если наоборот:
list.add(elem);
elem = list.remove(list.size() - 1);
То быстрее ArrayList (раза в 2-3)
ну в твоем случае ты имеешь около 4 млн рёбер, если каждое ребро будет по 16 байт, то ML тебе почти гарантирован. динамическая память штука такая, если ты выделяешь 1 байт с помощью оператора new даже в C++, реально ты выделишь 16 байт (может даже 32, наверное от платформы зависит)
можешь проверить мою гипотезу о 16 байтах посабмитив A+B, выделя память с помошью new.
Вот так я закэшировал интежеры, чтобы 49-й тест прошёл (но обломился 50-й).
Насчёт размера указателей вроде бы он тупо равен 32 байтам для 32-разрядных JVM, (но в принципе это на усмотрение авторов машины) но всё равно Vector явно не является просто массивом указателей, например, 4-разрядных, а содержит ещё O(size()) какой-то ерунды, т.к. если вручную попробовать на массив интов int[] заменить, всё проходит, как я выше написал в ответ топикстартеру... %)