leetcode 链表

90 阅读2分钟

链表

1、链表的合并

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

示例:

输入:1->2->4, 1->3->4 输出:1->1->2->3->4->4

const mergeTwoLists = function(l1, l2) {
  let head = new ListNode()
  let cur = head
  while(l1 && l2) {
    if(l1.val<=l2.val) {
      cur.next = l1
      l1 = l1.next
    } else {
      cur.next = l2
      l2 = l2.next
    }
    cur = cur.next 
  }
  
  cur.next = l1!==null?l1:l2
  return head.next
};

2、链表节点的删除

给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。

示例 1:

输入: 1->1->2 输出: 1->2 示例 2: 输入: 1->1->2->3->3 输出: 1->2->3

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

给定一个排序链表,删除所有含有重复数字的结点,只保留原始链表中 没有重复出现的数字。

示例 1:

输入: 1->2->3->3->4->4->5 输出: 1->2->5

示例 2:

输入: 1->1->1->2->3 输出: 2->3

const deleteDuplicates = function(head) {
  if(!head || !head.next) {
    return head
  }
  let dummy = new ListNode() 
  dummy.next = head   
  let cur = dummy 
  while(cur.next && cur.next.next) {
    if(cur.next.val === cur.next.next.val) {
      let val = cur.next.val
      while(cur.next && cur.next.val===val) {
        cur.next = cur.next.next 
      }
    } else {
      cur = cur.next
    }
  }
  return dummy.next;
};

3、删除链表的倒数第 N 个结点

给定一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

示例:

给定一个链表: 1->2->3->4->5, 和 n = 2. 当删除了倒数第二个结点后,链表变为 1->2->3->5.

说明:给定的 n 保证是有效的。

const removeNthFromEnd = function(head, n) {
  const dummy = new ListNode()
  dummy.next = head
  let fast = dummy
  let slow = dummy

  while(n!==0){
    fast = fast.next
    n--
  }
  
  while(fast.next){
    fast = fast.next
    slow = slow.next
  }
  
  slow.next = slow.next.next
  return dummy.next
};

4、完全反转一个链表

定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。

示例:

输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL

const reverseList = function(head) {
  let pre = null;
  let cur = head;
  while (cur !== null) {
    let next = cur.next;
    cur.next = pre;
    pre = cur;
    cur = next;
  }
  return pre
};

5、局部反转一个链表

反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。

说明:

1 ≤ m ≤ n ≤ 链表长度。

示例:

输入: 1->2->3->4->5->NULL, m = 2, n = 4 输出: 1->4->3->2->5->NULL

const reverseBetween = function(head, m, n) {
  let pre,cur,leftHead
  const dummy = new ListNode()  
  dummy.next = head
  let p = dummy  
  for(let i=0;i<m-1;i++){
    p = p.next
  }
  leftHead = p
  let start = leftHead.next  
  pre = start
  cur = pre.next
  for(let i=m;i<n;i++){
    let next = cur.next
    cur.next = pre
    pre = cur
    cur = next
  }
  leftHead.next = pre
  start.next=cur
  return dummy.next
};

6、环形链表

给定一个链表,判断链表中是否有环。

示例 1:

输入:[3,2,0,4](链表结构如下图) 输出:true 解释:链表中存在一个环

const hasCycle = function(head) {
  while(head){
    if(head.flag){
      return true;
    }else{
      head.flag = true;
      head = head.next;
    }
  }
  return false;
};

给定一个链表,返回链表开始入环的第一个结点。 如果链表无环,则返回 null。

示例 1:

输入:head = [3,2,0,-4](如下图)

输出:tail connects to node index 1

解释:链表中有一个环,其尾部连接到第二个结点

示例 2:

输入:head = [1,2](如下图) 输出:tail connects to node index 0 解释:链表中有一个环,其尾部连接到第一个结点。

示例 3:

输入:head = [1](如下图) 输出:no cycle 解释:链表中没有环。

const detectCycle = function(head) {
  while(head){
    if(head.flag){
      return head;
    }else{
      head.flag = true;
      head = head.next;
    }
  }
  return null;
};