leetcode
leetcode 2901 ~ 2950
回文链表

回文链表

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 239 ms, 内存: 28.1 MB


/*
 * 思路:
 * 1. 将链表转换为列表。
 * 2. 使用流来判断列表是否为回文。
 */
import java.util.*;
import java.util.stream.*;

class ListNode {
    int val;
    ListNode next;
    ListNode(int x) { val = x; }
}

public class Solution {
    public boolean isPalindrome(ListNode head) {
        List<Integer> values = new ArrayList<>();

        // Step 1: 将链表转换为列表
        ListNode current = head;
        while (current != null) {
            values.add(current.val);
            current = current.next;
        }

        // Step 2: 使用流来判断列表是否为回文
        return IntStream.range(0, values.size() / 2)
                        .allMatch(i -> values.get(i).equals(values.get(values.size() - 1 - i)));
    }
}

解释

方法:

此题解采用了快慢指针法来找到链表的中点,并在此过程中反转链表的前半部分。快指针每次移动两步,慢指针每次移动一步。当快指针到达链表末尾时,慢指针则位于中点。若链表长度为奇数,慢指针还需前进一步。之后,从中点将链表分为前后两部分,前半部分已在移动时被反转。然后分别从前半部分和后半部分的头部开始比较,若所有对应节点值相等,则链表为回文链表。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么在反转链表的同时采用快慢指针来找到中点,单独使用快慢指针定位中点然后再反转前半部分是否可行?
在反转链表的同时使用快慢指针可以有效地减少算法的时间复杂度和空间复杂度。如果先使用快慢指针定位到中点,然后再对前半部分进行反转,这样做虽然可行,但会导致需要两次遍历链表:一次是找中点,一次是反转前半部分。而同时操作可以仅通过一次遍历完成中点查找和前半部分的反转,从而使得整体效率更高。
🦆
快指针条件是`fast.next and fast.next.next`,请问这样的条件设置是为了确保什么?如果链表长度为偶数和奇数时,快慢指针的结束位置会如何不同?
条件`fast.next and fast.next.next`是为了确保快指针在移动时不会越界,同时可以确保快指针总是走两步,慢指针走一步。当链表长度为偶数时,快指针会停在链表的最后一个节点上,这时慢指针正好在中间位置的第一个节点上。而当链表长度为奇数时,快指针会停在倒数第二个节点上,这时慢指针位于中间位置的节点上。因此,在偶数长度的情况下,需要额外处理使慢指针前进一步至确切的中点位置。
🦆
在代码中处理奇数长度和偶数长度链表的方法是什么?具体是如何调整指针以准备比较回文?
在代码中,根据快指针的位置(是否有next节点)来调整慢指针的位置,以适应奇偶长度的链表。如果快指针有next节点(即长度为偶数),慢指针会前进到偶数链表的中间位置开始比较。如果快指针没有next节点(即长度为奇数),慢指针则不需要前进,因为它已经位于中间。然后通过调整指针,将慢指针的前半部分链表与后半部分进行比较,通过节点值比较来判断是否为回文链表。

相关问题