返回

征服LeetCode难题:92. 反转链表 II ── 细品迭代法精妙之处,JavaScript代码带详细注释

前端

反转链表 II:掌握迭代法,征服链表难题

认识链表

链表是一种广泛应用的数据结构,因其灵活性与便利性而备受青睐。然而,当面临反转链表的任务时,不少程序员难免望而却步。别担心,今天,我们将携手征服LeetCode 92题:反转链表 II,并为你揭晓迭代法这一反转利器。

理解题目要求

LeetCode 92题要求我们在链表的第m个节点到第n个节点之间进行反转。想象一下,我们有一条链表,像一条小火车一样,每个车厢代表一个节点。题目就是要我们把从第m节车厢到第n节车厢的车厢顺序调个个儿。

掌握迭代法

迭代法,顾名思义,是一种逐个元素地遍历链表,并根据特定规则进行操作的算法。在反转链表的场景中,我们利用迭代法将指定范围内的链表节点进行反转,从而实现整体链表的反转。

算法步骤

  1. 确定反转范围: 首先找到第m-1个节点和第m个节点,将它们分别记为prev和curr。
  2. 反转链表: 从第m个节点开始,将链表分成三段:反转第二段(从curr节点到n节点),保持第一段和第三段不变。
  3. 反转过程: 使用一个辅助指针next来保存curr节点的下一个节点。将curr节点的下一个节点指向prev节点,再将prev节点的下一个节点指向curr节点。不断重复此过程,直到curr节点指向n节点。
  4. 连接链表: 反转完成后,将第二段链表与第一段和第三段链表连接起来。

代码实现

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */

/**
 * @param {ListNode} head
 * @param {number} m
 * @param {number} n
 * @return {ListNode}
 */
const reverseBetween = (head, m, n) => {
  // Find the (m-1)th node and the mth node.
  let prev = null;
  let curr = head;
  for (let i = 1; i < m; i++) {
    prev = curr;
    curr = curr.next;
  }

  // Reverse the linked list from the mth node to the nth node.
  let next = null;
  for (let i = m; i <= n; i++) {
    next = curr.next;
    curr.next = prev;
    prev = curr;
    curr = next;
  }

  // Connect the reversed part with the rest of the linked list.
  if (prev) {
    prev.next = curr;
  } else {
    head = curr;
  }
  if (next) {
    curr.next = next;
  }

  // Return the head of the reversed linked list.
  return head;
};

结语

迭代法,作为反转链表的有效手段,因其简洁高效而受到广泛应用。在LeetCode 92题中,我们通过一步步拆解题目要求,将链表反转问题化繁为简。借助JavaScript的强大功能,我们实现了反转链表的迭代算法,并用详细注释为你一一剖析。希望本文能为你带来启发,助你在LeetCode的征程上披荆斩棘,勇往直前!

常见问题解答

  1. 为什么使用迭代法?
    迭代法可以逐个元素地遍历链表,并根据需要执行特定的操作。在反转链表的情况下,它允许我们在指定范围内轻松地反转节点。

  2. 算法中prev和next的作用是什么?
    prev指针指向当前节点的前一个节点,而next指针指向当前节点的下一个节点。它们在反转链表的过程中起到辅助作用,帮助我们改变节点之间的连接关系。

  3. 如何连接反转后的链表部分?
    反转完成后,我们需要将反转后的链表部分与第一段和第三段链表连接起来。如果反转的链表部分是链表的头部,则需要将反转部分的头部设置为链表的新头部;否则,将反转部分的尾部连接到第一段链表的尾部,并将反转部分的头部连接到第三段链表的头部。

  4. 时间复杂度和空间复杂度是多少?
    迭代法的时间复杂度为O(n),其中n是链表的长度。它需要遍历链表一次来反转指定范围内的节点。空间复杂度为O(1),因为算法不需要额外的空间来存储中间结果。

  5. 迭代法与递归法有什么区别?
    迭代法使用循环来遍历链表,而递归法使用函数调用自身来遍历链表。对于反转链表,迭代法通常更简单、更直接,而递归法可能会更复杂、但有时也更简洁。