回文链表-leetcode

题目描述

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false

示例 1:

img

输入:head = [1,2,2,1]
输出:true

示例 2:

img

输入:head = [1,2]
输出:false

提示:

  • 链表中节点数目在范围[1, 105]
  • 0 <= Node.val <= 9

进阶:你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

解法一

思路:

找到链表中间节点,将链表后半部分进行反向,然后在比较前后部分值是否相等。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public boolean isPalindrome(ListNode head) {
        if(head.next==null)return true;
        ListNode p = head,q;
        int listNodeLen=0;
        while (p != null) {
            listNodeLen++;
            p = p.next;
        }
        p=head;
        for (int i = 0; i < listNodeLen/2-1; i++) {
            p = p.next;
        }
        q=p.next;
        p.next = null;
        //长度为奇数
        if(listNodeLen%2!=0)q=q.next;
        ListNode head1=reverseList(q);
        while(head!=null){
            if(head.val != head1.val) return false;
            head=head.next;
            head1=head1.next;
        }
        return true;



    }
    public ListNode reverseList(ListNode head) {
        if(head == null || head.next == null) return head;
        ListNode p,q,r;
        p = head;q=head.next;r=head.next.next;
        while(true){
            if(p==head)p.next=null;
            q.next=p;
            p=q;
            q=r;
            if(q==null) break;
            r=r.next;
        }
        return p;
    }
}

解法二

思路:

来自官方解答。

之前是首先遍历完链表求得链表长度再来寻找中间节点,现在使用快慢指针。慢指针一次走一步,快指针一次走两步,快慢指针同时出发。当快指针移动到链表的末尾时,慢指针恰好到链表的中间。通过慢指针将链表分为两部分。

代码:

class Solution {
    public boolean isPalindrome(ListNode head) {
        if (head == null) {
            return true;
        }

        // 找到前半部分链表的尾节点并反转后半部分链表
        ListNode firstHalfEnd = endOfFirstHalf(head);
        ListNode secondHalfStart = reverseList(firstHalfEnd.next);

        // 判断是否回文
        ListNode p1 = head;
        ListNode p2 = secondHalfStart;
        boolean result = true;
        while (result && p2 != null) {
            if (p1.val != p2.val) {
                result = false;
            }
            p1 = p1.next;
            p2 = p2.next;
        }

        // 还原链表并返回结果
        firstHalfEnd.next = reverseList(secondHalfStart);
        return result;
    }

    private ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode nextTemp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = nextTemp;
        }
        return prev;
    }

    private ListNode endOfFirstHalf(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while (fast.next != null && fast.next.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }
}

解法三

采用递归的方法。递归会从尾向头返回,再定义一个前指针,判断前后指针是否相等。

1

2

3

4

5

14

7

8

9

10

11

12

13

14

代码:

class Solution {
    private ListNode frontPointer;

    private boolean recursivelyCheck(ListNode currentNode) {
        if (currentNode != null) {
            if (!recursivelyCheck(currentNode.next)) {
                return false;
            }
            if (currentNode.val != frontPointer.val) {
                return false;
            }
            frontPointer = frontPointer.next;
        }
        return true;
    }

    public boolean isPalindrome(ListNode head) {
        frontPointer = head;
        return recursivelyCheck(head);
    }
}
posted @ 2025-09-28 20:44  狐狸胡兔  阅读(7)  评论(0)    收藏  举报