Linked list in JavaScript

4 min read
class Node {
  constructor(data, next = null) {
    this.data = data;
    this.next = next;
  }
}
 
class LinkedList {
  constructor(head) {
    this.head = head;
  }
  
  addToHead(data) {
    this.head = new Node(data, this.head);
  }
  
  addToTail(data) {
    if (!this.head) {
      this.head = new Node(data, null);
      return;
    }
 
    let node = this.head;
 
    while(node.next !== null) {
      node = node.next;
    }
 
    node.next = new Node(data, node);
  }
}
 
const node_1 = new Node('foo');
const node_2 = new Node('bar', node_1);
const list = new LinkedList(node_1);

The middle point of the linked list

  1. 藉由 slowfast 兩個指標
  2. slow 每次前進一個節點,fast 每次前進兩個節點
  3. fast 為最後節點,或無法前進兩個節點時,slow 即為中間的 node
function midpoint(list) {
  let slow = list.head;
  let fast = list.head;
  
  while (fast.next && fast.next.next) {
    slow = slow.next;
    fast = fast.next.next;
  }
  
  return slow;
}

Check is a circular linked list

  1. 藉由 slowfast 兩個指標
  2. slow 每次前進一個節點,fast 每次前進兩個節點
  3. 若 linked list 存在 cycle,fast 最終會追上 slow
function circular(list) {
  if (!list.head) {
    return false;
  }
 
  let slow = list.head;
  let fast = list.head;
  let result = false;
  
  while (fast.next && fast.next.next) {
    slow = slow.next;
    fast = fast.next.next;
 
    if (slow === fast) {
      result = true;
      break;
    }
  }
  
  return result;
}

Get n’th node from the end of a linked list

Assume that n will always be less than the length of the list.
fromLast(list, 0).data d
fromLast(list, 2).data b
  1. 先將 fast 位移 n 個節點
  2. fast 為 tail node 時,slow 即為從 linked list 結尾開始,從 0 算起第 n 個 node
function fromLast(list, n) {
  let slow = list.head;
  let fast = list.head;
  
  while (n > 0) {
    fast = fast.next;
    n--;
  }
  
  while (fast.next) {
    slow = slow.next;
    fast = fast.next;
  }
  
  return slow;
}

Reverse a linked list

這邊透過三個變數交換的方式,來改變 node.next 指向

大致流程如下

  null--->1--->2--->3--->4--->5--->null
  |       |
  |       current
  previous

  // temporary = current
  // current = current.next

  null--->1--->2--->3--->4--->5--->null
  |       |    |
  |       |    current
  |       temporary
  previous

  // temporary.next = previous

  null<---1--->2--->3--->4--->5--->null
  |       |    |
  |       |    current    
  |       temporary       
  previous 

  // previous = temporary

  null<---1--->2--->3--->4--->5--->null
          |    |
          |    current
          temporary
          previous

程式碼實作如下

function reverseList(head) {
  if (!head || !head.next) {
    return head;
  }
  
  let current = head;
  let previous = null;
  let temporary;
  
  while (current !== null) {
    temporary = current;
    current = current.next;
    temporary.next = previous;
    previous = temporary;
  }
  
  return previous;
};

Reference

The Coding Interview Bootcamp: Algorithms + Data Structures