返回

破解LeetCode 234:探寻回文链表的奥秘**

闲谈

判定回文链表:揭秘两种经典算法

何谓回文链表?

在数据结构的王国里,链表是一种常用的存储数据方式。它就像一串珍珠项链,每个珍珠代表一个节点,节点之间用指针相连。而回文链表,顾名思义,就是正向和反向读取节点元素都能得到相同结果的链表。比如 [1, 2, 2, 1] 就是一个回文链表,而 [1, 2, 3, 4] 则不是。

算法揭秘:递归 vs 指针

判定回文链表有两种常见的算法:递归法和指针法。

递归法

递归就像一场迷宫寻宝游戏。我们先将链表一分为二,递归地检查前半部分是否回文。如果前半部分回文,我们再将后半部分与递归验证过的前半部分进行比较。如果两者一致,那么整个链表就是回文的。

指针法

指针法则像一场双人接力赛。我们使用两个指针,一个从链表头部出发,一个从链表尾部出发。这两个指针同时向前遍历链表,如果链表回文,那么它们会在链表中间相遇。

代码实现:JavaScript

const isPalindrome = (head) => {
  if (!head || !head.next) return true;

  let slow = head;
  let fast = head;

  while (fast && fast.next) {
    slow = slow.next;
    fast = fast.next.next;
  }

  if (fast) slow = slow.next;

  let prev = null;
  while (slow) {
    const next = slow.next;
    slow.next = prev;
    prev = slow;
    slow = next;
  }

  while (head && prev) {
    if (head.val !== prev.val) return false;
    head = head.next;
    prev = prev.next;
  }

  return true;
};

代码详解

我们从链表的头部和尾部各派出一个指针,让它们同时向中间移动。指针移动的速度是 1:2,即第二个指针的速度是第一个指针的两倍。这样当第二个指针到达链表尾部时,第一个指针刚好到达链表中间。然后,我们反转链表的后半部分,并逐个比较反转后的后半部分与前半部分,如果元素一致则说明链表回文。

常见问题解答

1. 为什么回文链表的前半部分需要递归检查?

递归检查前半部分的目的是确定链表前半部分是否回文,如果前半部分不是回文,那么整个链表肯定不是回文。

2. 指针法中两个指针的速度为什么是 1:2?

当第二个指针到达链表尾部时,第一个指针正好到达链表中间,这是我们判定回文的关键。

3. 为什么反转链表的后半部分?

反转链表的后半部分是为了方便比较,这样可以将链表的两个部分视为两个独立的子链表进行比较。

4. 如果链表长度是奇数,递归检查时前半部分应该递归到哪一个节点?

如果链表长度是奇数,那么递归检查时前半部分应该递归到链表中间节点的前一个节点。

5. 如果链表长度是 1,直接返回 true 即可吗?

是的,如果链表长度是 1,说明链表中只有一个节点,肯定是回文的,直接返回 true 即可。

结语

掌握回文链表的判定算法对于提升我们的编程能力大有裨益。无论是使用递归法还是指针法,理解算法背后的思想和逻辑至关重要。希望这篇文章能帮助你深入理解回文链表判定算法,下次遇到类似问题时,你可以从容应对,轻松解决。