Double LinkedList
class ListNode {
int val;
ListNode next;
ListNode prev;
ListNode(int x) {
val = x;
}
}
class LinkedList {
int size;
// pseudo-head and pseudo-tail
ListNode head;
ListNode tail;
public LinkedList() {
size = 0;
head = new ListNode(0);
tail = new ListNode(0);
head.next = tail;
tail.prev = head;
}
/**
* Get the value of the index-th node in the linked list. If the index is invalid, return -1.
*/
public int get(int index) {
// if index is invalid
if (index < 0 || index >= size) {
return -1;
}
// choose the fastest way: to move from the head
// or to move from the tail
ListNode node = head;
if (index + 1 < size - index) {
for (int i = 0; i < index + 1; ++i) {
node = node.next;
}
} else {
node = tail;
for (int i = 0; i < size - index; ++i) {
node = node.prev;
}
}
return node.val;
}
/**
* Add a node of value val before the first element of the linked list. After the insertion, the
* new node will be the first node of the linked list.
*/
public void addAtHead(int val) {
ListNode predecessor = head;
ListNode successor = head.next;
++size;
ListNode toAdd = new ListNode(val);
toAdd.prev = predecessor;
toAdd.next = successor;
predecessor.next = toAdd;
successor.prev = toAdd;
}
/**
* Append a node of value val to the last element of the linked list.
*/
public void addAtTail(int val) {
ListNode successor = tail, predecessor = tail.prev;
++size;
ListNode toAdd = new ListNode(val);
toAdd.prev = predecessor;
toAdd.next = successor;
predecessor.next = toAdd;
successor.prev = toAdd;
}
/**
* Add a node of value val before the index-th node in the linked list. If index equals to the
* length of linked list, the node will be appended to the end of linked list. If index is greater
* than the length, the node will not be inserted.
*/
public void addAtIndex(int index, int val) {
// If index is greater than the length,
// the node will not be inserted.
if (index > size) {
return;
}
// [so weird] If index is negative,
// the node will be inserted at the head of the list.
if (index < 0) {
index = 0;
}
// find predecessor and successor of the node to be added
ListNode predecessor, successor;
if (index < size - index) {
predecessor = head;
for (int i = 0; i < index; ++i) {
predecessor = predecessor.next;
}
successor = predecessor.next;
} else {
successor = tail;
for (int i = 0; i < size - index; ++i) {
successor = successor.prev;
}
predecessor = successor.prev;
}
// insertion itself
++size;
ListNode toAdd = new ListNode(val);
toAdd.prev = predecessor;
toAdd.next = successor;
predecessor.next = toAdd;
successor.prev = toAdd;
}
/**
* Delete the index-th node in the linked list, if the index is valid.
*/
public void deleteAtIndex(int index) {
// if the index is invalid, do nothing
if (index < 0 || index >= size) {
return;
}
// find predecessor and successor of the node to be deleted
ListNode predecessor, successor;
if (index < size - index) {
predecessor = head;
for (int i = 0; i < index; ++i) {
predecessor = predecessor.next;
}
successor = predecessor.next.next;
} else {
successor = tail;
for (int i = 0; i < size - index - 1; ++i) {
successor = successor.prev;
}
predecessor = successor.prev.prev;
}
// delete pred.next
--size;
predecessor.next = successor;
successor.prev = predecessor;
}
}
Last updated