几个链表的题目

前言

找到了个不错的提纲,做了些反转链表的题目

反转链表

循环和递归,以下三段分别为定义,循环,递归 1,递归 2

function ListBode(val) {
  this.val = val;
  this.next = null;
}
function reverseList = head => {
  if(!head) return head
  let cur = head, pre = null
  while(cur) {
    let next = cur.next;
    cur.next = pre
    pre = cur
    cur = next
  }
  return pre
}
function reverseList = head => {
  if(!head || !head.next) return head
  let res = reverseList(head.next)
  head.next.next = head
  head.next = null
  return res
}
function reverseList = head => {
  if(!head) return head
  let help = (cur, pre) => {
    if(!cur) return pre
    let next = cur.next
    cur.next = pre
    return help(next, cur)
  }
  return help(head)
}

区间反转

同样分别使用循环和递归:

function PartReverseList = (head, m, n) => {
  let count = n-m;
  let p = dummy = new ListNode()
  let start, tail, cur, pre;
  p.next = head
  for(i = 0; i< m-1; i++) {
    p = p.next
  }
  start = p;
  pre = tail = p.next;
  cur = pre.next;
  while(count){
    let next = cur.next;
    cur.next = pre
    pre = cur
    cur = next
    count--
  }
  start.next = pre
  tail.next = cur
  return dummy.next
}
function PartReverseList = (head, m, n) => {
  let help = (cur, pre) => {
    if(!cur) return pre
    let next = cur.next
    cur.next = pre
    return help(next, cur)
  }
  let p = dummy = new ListNode()
  p.next = head
  let start, end, front, tail;
  for(i = 0; i<m-1; i++) {
    p = p.next
  }
  front = p
  start = p.next
  for(i = m-1; i<n;i++) {
    p = p.next
  }
  end = p
  tail = p.next
  end.next = null
  front.next = help(start)
  start.next = tail
  return dummy.next
}

两两交换链表中的节点

同样使用循环和递归两种方式来做

function TwoChange(head) {
  if (!head||!head.next) return head
  let dummy = p = new ListNode()
  p.next = head
  while(p.next&&p.next.next) {
    let node1 = p.next, node2 = p.next.next
    node1.next = node2.next
    node2.next = node1
    p.next = node2
    p = node1
  }
  return dummy.next
}
function TwoChange(head) {
  if (!head||!head.next) return head
  let node1 = head, node2 = head.next
  node1.next = TwoChange(node2.next)
  node2.next = node1
  return node2
}

环形链表

使用集合 || 使用双指针

function circle(head) {
  let dic = new Set();
  while (head) {
    if (dic.has(head)) return true;
    dic.add(head);
    head = head.next;
  }
  return false;
}
function circle(head) {
  let fast = head,
    slow = head;
  while (fast && fast.next && fast.next.next) {
    fast = fast.next.next;
    slow = slow.next;
    if (fast === slow) {
      return true;
    }
  }
  return false;
}

链表合并

同样有两种方式,循环和递归,由于递归较为简单,所以放在前面

function merge(l1, l2) {
  if (!l1) return l2;
  if (!l2) return l1;
  if (l1.val > l2.val) {
    l2.next = merge(l1, l2.next);
    return l2;
  } else {
    l1.next = merge(l2, l1.next);
    return l1;
  }
}
function merge(l1, l2) {
  if (!l1) return l2;
  if (!l2) return l1;
  let p = (dummy = new ListNode());
  while (l1 && l2) {
    if (l1.val > l2.val) {
      p.next = l2;
      p = p.next;
      l2 = l2.next;
    } else {
      p.next = l1;
      p = p.next;
      l1 = l1.next;
    }
  }
  if (l1) p.next = l1;
  else p.next = l2;
  return dummy.next;
}

回文链表

分别使用数组和找链表中点并反转的方式来实现

function isPalindrome(head) {
  let res = [];
  while (head) {
    res.push(head.val);
    head = head.next;
  }
  let str1 = res.join(""),
    str2 = res.reverse().join("");
  return str1 === str2;
}
function isPalindrome(head) {
  let reverse = (cur, pre) => {
    if (!cur) return pre;
    let next = cur.next;
    cur.next = pre;
    return reverse(next, cur);
  };
  let dummy = (slow = fast = new ListNode());
  dummy.next = head;
  while (fast && fast.next) {
    slow = slow.next;
    fast = fast.next.next;
  }
  let next = slow.next;
  slow.next = null;
  let newStart = reverse(next);
  for (let p = head, newP = newStart; newP; p = p.next, newP = newP.next) {
    if (p.val != newP.val) {
      return false;
    }
  }
  return true;
}
发布了362 篇原创文章 · 获赞 352 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_43870742/article/details/104117151