Linked List

Approach

We can use size property to easily and efficiently delete at head and tail.

Complexity

  • Time complexity:
    • get(index): Worst Time complexity $$O(n)$$
    • addAtHead(val): $O(1)$
    • addAtTail(val): $O(1)$
    • addAtIndex(index, val): Worst Time complexity $O(n)$ but for special cases where we want to read at tail, it's $O(1)$
    • deleteAtIndex(index, val): Worst Time complexity $O(n)$ but for special cases where we want to delete at tail, it's $O(1)$

Code

class Node {
    constructor(value) {
        this.value = value;
        this.pre = null;
        this.post = null;
    }
}

var MyLinkedList = function() {
    this.head = null;
    this.tail = null;
    this.size = 0;
};

/** 
 * @param {number} index
 * @return {number}
 */
MyLinkedList.prototype.get = function(index) {
    let node = this.getNodeAtIndex(index);

    if (node == null) {
        return -1;
    }

    return node.value;
};

/** 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtHead = function(val) {
    let node = new Node(val);

    if (this.tail == null) {
        this.tail = node;
    }
    
    if (this.head != null) {
        this.head.pre = node;
        node.post = this.head;
    }
    this.head = node;
    this.size++;
};

/** 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtTail = function(val) {
    let node = new Node(val);

    if (this.head == null) {
        this.head = node;
    }

    if (this.tail != null) {
        node.pre = this.tail;
        this.tail.post = node;
    }

    this.tail = node;
    this.size++;
};

/** 
 * @param {number} index 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.getNodeAtIndex = function(index) {
    
    let node = this.head;
    for (let i = 0; i < index && node != null; i++) {
        node = node.post;
    }
    return node;
}

/** 
 * @param {number} index 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtIndex = function(index, val) {

    if (index > this.size) {
        return;
    }

    if (index == 0) {
        return this.addAtHead(val);
    }
    if (index == this.size) {
        return this.addAtTail(val);
    }

    let node = this.getNodeAtIndex(index);

    let newNode = new Node(val);

    newNode.post = node;
    newNode.pre = node.pre;

    node.pre.post = newNode;
    node.pre = newNode;
    this.size++;
};


MyLinkedList.prototype.deleteAtHead = function() {
    if (this.head != null) {
        // this.head.pre = null;
        this.head = this.head.post;
        this.size--;
    }

    if (this.size == 0) {
        this.tail = null;
    }
}

MyLinkedList.prototype.deleteAtTail = function() {
    if (this.tail != null) {
        this.tail.pre.post = null;
        this.tail = this.tail.pre;
        this.size--;
    }

    if (this.size == 0) {
        this.head = null;
    }
}

/** 
 * @param {number} index
 * @return {void}
 */
MyLinkedList.prototype.deleteAtIndex = function(index) {

    if (index == 0) {
        this.deleteAtHead();
        return;
    }

    if (index == this.size - 1) {
        this.deleteAtTail();
        return;
    }

    let node = this.getNodeAtIndex(index);

    if (node == null) {
        return;
    }

    this.size--;

    if (this.head == node) {
        this.head = null;
    }

    if (this.tail == node) {
        this.tail = null;
    }

    if (node.pre != null) {
        node.pre.post = node.post;
    }

    if (node.post != null) {
        node.post.pre = node.pre;
    }
};


MyLinkedList.prototype.print = function() {
    let node = this.head;
    let list = ['List:'];
    for ( ; node != null; ) {
        list.push(node.value)
        node = node.post;
    }

    console.log(list.join(' '))
}


let list = new MyLinkedList();

list.addAtHead(1)
list.print()
list.addAtTail(3)
list.print()
list.addAtIndex(1, 2)
list.print()
console.log(list.get(1))
list.print()
list.deleteAtIndex(0)
list.print()
console.log(list.get(0))
list.print()


Home | © 2024 Last Updated: Mar 03, 2024
Buy Me A Coffee