做个记录吧!链表算法 javascript实现

59 阅读4分钟

使用javascript实现常用leecode算法---链表篇

前端面试 必备算法

实现链表

class Node {
    constructor(val, next) {
      this.val = val === undefined ? 0 : val;
      this.next = next === undefined ? null : next;
    }
}
class LinkedList {
    constructor(value) {
      this.head = new Node(value);
    }
    append(val) {
      const newNode = new Node(val);
      let currentNode = this.head;
      while (currentNode.next) {
        currentNode = currentNode.next;
      }
      currentNode.next = newNode;
    }
}
var node = new LinkedList();
先后插入4519
node.append(4);
node.append(5);
node.append(1);
node.append(9);
const _node = node.head.next; 

1.合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

输入:l1 = [1,2,4], l2 = [1,3,4] 输出:[1,1,2,3,4,4]

输入:l1 = [], l2 = [] 输出:[]

var mergeTwo = function(l1, l2){
    let node = new Node('1');
    let pre = node;
    while(l1!==null && l2!==null){
      if(l1.val<l2.val){
        pre.next = l1;
        l1 = l1.next;
      }else{
        pre.next = l2;
        l2 = l2.next;
      }
      pre = pre.next;
    }
    pre.next = l1==null?l2:l1;
    return node.next;
  }
  var mergeTwoLists = function(l1, l2){
    if(l1==null) return l2;
    if(l2==null) return l1;
    if(l1.val<l2.val){
      l1.next = mergeTwo(l1.next, l2);
      return l1;
    }else{
      l2.next = mergeTwo(l1, l2.next);
      return l2;
    }
  }

2.反转从位置 m 到 n 的链表,其他正常返回

var reverseBetween = function (head, m, n) {
    if (head == null || head.next == null || m == n) {
      return head;
    }
    let node = new Node("a", head);
    let p0 = node;
    for (var i = 0; i < m - 1; i++) {
      p0 = p0.next;
    }
    let pre = null;
    let cur = p0.next;
    for (var j = 0; j < n - m + 1; j++) {
      let next = cur.next;
      cur.next = pre;
      pre = cur;
      cur = next;
    }
    p0.next.next = cur;
    p0.next = pre;
    return node.next;
    };

3.k个一组翻转链表

[1,2,3,4,5] k=2 返回:[2,1,4,3,5]

const reverseK = function (head, k) {
    var n = 0;
    var cur = head;
    while (cur !== null) {
      n++;
      cur = cur.next;
    }
    var temp = new Node("a", head);
    var p0 = temp;
    cur = p0.next;
    let pre = null;
    while (n >= k) {
      n = n - k;
      for (var i = 0; i < k; i++) {
        var next = cur.next;
        cur.next = pre;
        pre = cur;
        cur = next;
      }
      x = p0.next;
      p0.next.next = cur;
      p0.next = pre;
      p0 = x;
    }
    return temp.next;
  };

4.返回链表的中间节点 [1,2,3,4,5]返回3 [1,2,3,4,5,6]返回4

const findMiddleNode1 = function (head) {
    let fast = head;
    let slow = head;
    while (fast && fast.next) {
      fast = fast.next.next;
      slow = slow.next;
    }
    return slow;
  };

5.环形链表 是否有环

const isCircle = function (head) {
    let fast = head;
    let slow = head;
    while (fast && fast.next) {
      fast = fast.next.next;
      slow = slow.next;
      if (fast == slow) {
        return true;
      }
    }
    return false;
  };

6.环形链表II

输入:head = [3,2,0,-4], pos = 1 输出:返回索引为 1 的链表节点,解释:链表中有一个环,其尾部连接到第二个节点。

var detectCycle = function (head) {
    let fast = head;
    let slow = head;
    while (fast && fast.next) {
      fast = fast.next.next;
      slow = slow.next;
      // 相遇了
      if (fast == slow) {
        fast = head;
        while (fast != slow) {
          fast = fast.next;
          slow = slow.next;
        }
        return slow;
      }
    }
    return null;
}

7.删除链表中的节点

head = [4,5,1,9], node = 5 输出:[4,1,9]

const deleteNode = function(head, num){
    let node = new Node('1', head);
    let cur = node;
    while(cur.next != null){
        if(cur.next.val == num){
            cur.next = cur.next.next;
        }
        cur = cur.next;
    }
    return node.next;
  }

8.删除链表的倒数第N个节点

输入:head = [1,2,3,4,5,6], n = 2 输出:[1,2,3,4,6]

const removeLastN = function(head, n){
    let node = new Node("a", head);
    let fast = node;
    let slow = node;
    while(n>0 && fast!=null){
      fast = fast.next;
      n--;
    }
    fast = fast.next;
    while(fast!=null){
      fast = fast.next;
      slow = slow.next;
    }
    slow.next = slow.next.next; 
    return node.next;
  }

9.删除排序链表中的重复元素

输入:head = [1,1,2] 输出:[1,2] 输入:head = [1,1,2,3,3] 输出:[1,2,3]

      const removeDoubleNode = function(head){
        if(head==null || head.next==null){
            return head;
        }
        let cur = head;
        while(cur && cur.next){
            if(cur.next.val===cur.val){
                cur.next = cur.next.next;
            }else{
                cur = cur.next;
            }
        }
        return node.next;
      }

10. 删除排序链表中的重复元素 II

给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。 输入:head = [1,2,3,3,4,4,5] 输出:[1,2,5]

const removeDoubleNode1 = function(head){
    let node = new Node('1', head);
    let cur = node;
    while(cur.next && cur.next.next){
        if(cur.next.val == cur.next.next.val){
            let x = cur.next.val;
            while(cur.next && cur.next.val ===x){
                cur.next = cur.next.next;
            }
        }else{
            cur = cur.next;
        }
    }
    return node.next;
  }

11.重排链表

给定一个单链表 L 的头节点 head ,单链表 L 表示为:L0 → L1 → … → Ln - 1 → Ln请将其重新排列后变为:L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

// 找到中间节点
    const findMidNode = function (head) {
        let fast = head;
        let slow = head;
        while (fast && fast.next) {
          fast = fast.next.next;
          slow = slow.next;
        }
        return slow;
      };
      // 反转链表
      const reverseNode = function (head) {
        let cur = head;
        let pre = null;
        while (cur !== null) {
          let next = cur.next;
          cur.next = pre;
          pre = cur;
          cur = next;
        }
        return pre;
      };
      const reorderList = function (head) {
        // 找到中间的节点
        let node = findMidNode(head);
        // 反转
        let p1 = reverseNode(node);
        // 拼接
        let p0 = head;
        while (p1.next !== null) {
          let x = p0.next;
          let x1 = p1.next;
          p0.next = p1;
          p1.next = x;
          p0 = x;
          p1 = x1;
        }
      };

12.分隔链表

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 输入:head = [1,4,3,2,5,2], x = 3 输出:[1,2,2,4,3,5] 输入:head = [2,1], x = 2 输出:[1,2]

const partition = function(head, x){
        if(head==null || head.next==null){
          return head;
        }
        const less = new Node('a');
        const more = new Node('b');
        const cur = less;
        const cur_1 = more;
        while(head!==null){
          if(head.val >= x){
            more.next = head;
            more = more.next;
          }else{
            less.next = head;
            less = less.next;
          }
          head = head.next;
        }
        more.next = null;
        less.next = cur_1.next;
        return cur.next;
      }