一文搞定翻转链表问题

117 阅读1分钟

翻转链表(递归实现)

function reverseList(head) {
  if (head == null || head.next == null) return head
  const node = head, tail = head.next
  const _list = reverseList(tail)
  node.next = tail.next
  tail.next = node
  return _list
}

翻转前 n 个链表(递归实现)

function reverseN(head, n) {
  // 这段逻辑往后数,看节点有没有 n 个
  let node = head
  for (let i = 0; i < n; i++) {
    if (node == null) return head
    node = node.next
  }
  // 这里是真正递归的逻辑
  if (n === 1) return head
  const newTail = head.next, newHead = reverseN(head.next, n - 1)
  head.next = newTail.next
  newTail.next = head
  return newHead
}

翻转区间链表

function reverseBetween(head, left, right) {
  if (left === 1) return reverseN(head, right)
  head.next = reverseBetween(head.next, left - 1, right - 1)
  return head
}

// 翻转前 n 个,这里没有考虑数量不足的情况
function reverseN(head, n) {
  if (n === 1) return head
  const newTail = head.next, newHead = reverseN(head.next, n - 1)
  head.next = newTail.next
  newTail.next = head
  return newHead
}

k 个一组翻转链表

function reverseKGroup(head, k) {
  // 虚拟头节点
  const dummuHead = new ListNode(null, head)
  // curr 永远指向上一次翻转过后的链表的尾节点
  let curr = dummuHead
  do {
    // 标记翻转后的尾节点
    const newTail = curr.next
    // 每次都翻转以 curr.next 为头的 k 个节点 
    curr.next = reverseN(curr.next, k)
    curr = newTail
  } while (curr && curr.next)
  return dummuHead.next
}

function reverseN(head, n) {
  // 这段逻辑往后数,看节点有没有 n 个
  let node = head
  for (let i = 0; i < n; i++) {
    if (node == null) return head
    node = node.next
  }
  // 这里是真正递归的逻辑
  if (n === 1) return head
  const newTail = head.next, newHead = reverseN(head.next, n - 1)
  head.next = newTail.next
  newTail.next = head
  return newHead
}