幾個鏈表的題目

前言

找到了個不錯的提綱,做了些反轉鏈表的題目

反轉鏈表

循環和遞歸,以下三段分別爲定義,循環,遞歸 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;
}
發佈了386 篇原創文章 · 獲贊 411 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章