Как уже говорилось, в общем случае это невозможно, нужно предположить что-то относительно сложности отдельных операций.Если у вас есть постоянное время next()
и previous()
для итераторов, используйте уже данное решение.Он должен работать как для LinkedList, так и для ArrayList.
Я думал о решении, которое будет работать для односвязного списка (но не для чего-то вроде ArrayList), но, к сожалению, метод ListIterators add
вставляет элемент передкурсор вместо того, чтобы после него, таким образом, это не выполнимо с интерфейсами List + ListIterator (если мы не можем исправить реализацию ListIterator, чтобы кэшировать элемент предварительной вставки, чтобы позволить один previous()
после add
в O (1))).
Здесь предполагается простой класс Node
с указателем следующего:
/**
* reverses a singly linked list.
* @param first the fist node. This will be the new last node.
* @param last the last node. This will be the new first node.
*/
void reverseList(Node first, Node last) {
while(first != last) {
Node temp = first;
first = temp.next;
temp.next = last.next;
last.next = temp;
}
}
В терминах индекса это будет примерно так:
public void reverseList(List<T> list) {
int index = list.size() -1;
while(n > 0) {
T element = list.remove(0);
list.add(n, element);
n--;
}
}
В терминах ListIterator это будет что-то вроде этого:
public void reverseList(List<T> list) {
ListIterator<T> it = list.listIterator(list.size());
while(it.previousIndex() > 0) { // we could count ourself here, too
T element = list.remove(0);
it.add(element);
it.previous();
}
}
Конечно, обычные реализации односвязных списков не будут иметь реализацию O (1) previous
, таким образом, она не будет работать там,как сказано ранее.(И они могут выдать исключение ConcurrentModificationException или вернуть ошибочный previousIndex
.)