234. 回文链表

本文详细介绍如何使用快慢指针及反转链表的方法来判断一个链表是否为回文结构,提供了两种实现方式,包括两个while循环和三个while循环的代码示例,帮助读者深入理解算法原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

234. 回文链表
判断一个链表是否为回文结构
在这里插入图片描述

题解:快慢指针 + 反转链表

1. 题解一:两个while循环

快指针走到末尾,慢指针刚好到中间,其中慢指针将前半部分反转,然后比较反转后的前半部分与原来的后半部分是否相同。
在这里插入图片描述
在这里插入图片描述

2. 题解二:三个while循环(首选)

  • 其一,find mid node:使用快慢指针找到链表中点。
  • 其二,reverse:逆序后半部分。
  • 其三,check:两个指针分别指向链表首尾两端,然后向链表中间进行移动并比较判断是否相同。
    在这里插入图片描述
    偶数节点情况:
    在这里插入图片描述
    奇数节点情况:
    在这里插入图片描述
    在这里插入图片描述

代码:快慢指针 + 反转链表

1. 代码一:两个while循环

public class code234 {

    public static boolean isPalindrome(ListNode head) {
        if(head == null || head.next == null)
        {
            return true;
        }
        /* 定义快慢两个指针 */
        ListNode slow = head;
        ListNode fast = head;
        /* 虚拟指针 */
        ListNode cur = head;
        ListNode pre = null;
        /* 找中点的时候完成反转 */
        // 快指针走到末尾,慢指针刚好到中间。其中慢指针将前半部分反转。(偶数个链表)
        while(fast != null && fast.next != null)
        {
            cur = slow;
            slow = slow.next;
            fast = fast.next.next;
            cur.next = pre;
            pre = cur;
        }
        /* 奇数个链表 */
        if(fast != null)
        {
            slow = slow.next;
        }
        // 然后比较反转后的前半部分与原来的后半部分是否相同
        while(cur != null && slow != null)
        {
            if(cur.val != slow.val)
            {
                return false;
            }
            cur = cur.next;
            slow = slow.next;
        }
        return true;
    }

    private static ListNode createLinkedList(int[] arr) {// 将输入的数组输入到链表中
        if (arr.length == 0) {
            return null;
        }
        ListNode head = new ListNode(arr[0]);
        ListNode current = head;
        for (int i = 1; i < arr.length; i++) {// 过程
            current.next = new ListNode(arr[i]);
            current = current.next;
        }
        return head;
    }

    private static void printLinkedList(ListNode head) {// 将链表结果打印
        ListNode current = head;
        while (current != null) {
            System.out.printf("%d -> ", current.val);
            current = current.next;
        }
        System.out.println("NULL");
    }

    public static void main(String[] args) {
        int[] x = { 1, 2, 2, 1 };
        ListNode list = createLinkedList(x);
        printLinkedList(list);
        boolean res = isPalindrome(list);
        System.out.println(res);
    }
}

2. 代码二:三个while循环(首选)

public class code234 {

    public static boolean isPalindrome(ListNode head) {
        if (head == null) {
            return true;
        }
        //通过快慢指针找到链表的中间节点
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }

        // 反转后半边的链表
        ListNode pre = null;
        while (slow != null) {
            ListNode temp = slow.next;
            slow.next = pre;
            pre = slow;
            slow = temp;
        }

        // 从链表两头到中间,比较两个子链表,判断是相同。(head指向前半链表表头,从前往后遍历;pre指向后半链表表头,从后往前遍历)
        while (head != null && pre != null) {
            if (head.val != pre.val) {
                return false;
            } else {
                pre = pre.next;
                head = head.next;
            }
        }
        return true;
    }

    private static ListNode createLinkedList(int[] arr) {// 将输入的数组输入到链表中
        if (arr.length == 0) {
            return null;
        }
        ListNode head = new ListNode(arr[0]);
        ListNode current = head;
        for (int i = 1; i < arr.length; i++) {// 过程
            current.next = new ListNode(arr[i]);
            current = current.next;
        }
        return head;
    }

    private static void printLinkedList(ListNode head) {// 将链表结果打印
        ListNode current = head;
        while (current != null) {
            System.out.printf("%d -> ", current.val);
            current = current.next;
        }
        System.out.println("NULL");
    }

    public static void main(String[] args) {
        int[] x = {1, 2, 2, 1};
        ListNode list = createLinkedList(x);
        printLinkedList(list);
        boolean res = isPalindrome(list);
        System.out.println(res);
    }
}

参考:

  1. 我的快慢指针都从头开始,感觉更好理解
  2. C++ 使用数组&反转链表
  3. 234.java 双指针 图解!
  4. 动画演示 234. 回文链表
  5. 【回文链表】两种方法,详细图解
  6. 回文链表
  7. 回文链表(1.栈,2.快慢指针+翻转)
  8. java,通俗易懂,原地进行,没有额外空间
### 判断回文链表的C++实现 为了判断一个单链表是否为回文链表,可以采用双端队列法或快慢指针加反转部分链表的方法。这里提供一种较为高效的算法——通过快慢指针找到链表中点并反转前半部分链表来进行比较。 #### 方法概述 利用两个速度不同的指针遍历整个列表:一个是每次移动一步(slow),另一个则是每两次才前进一次(fast)。当 fast 达到终点时,slow 正好位于中间位置。接着将 slow 后面的部分进行翻转并与前面未改变顺序的一半做对比即可得出结论[^1]。 下面是具体的 C++ 实现: ```cpp #include <iostream> using namespace std; // 定义链表节点结构体 struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(nullptr) {} }; bool isPalindrome(ListNode* head) { if (!head || !head->next) return true; // 空链表或只有一个元素的情况 ListNode *slow = head, *fast = head; stack<int> stk; while (fast != nullptr && fast->next != nullptr){ stk.push(slow->val); slow = slow->next; fast = fast->next->next; } // 如果长度为奇数,则跳过中心结点 if(fast!=nullptr){ slow=slow->next; } while (slow != nullptr){ int topVal = stk.top(); stk.pop(); if(topVal != slow -> val){ return false; }else{ slow = slow -> next; } } return true; } ``` 此段程序首先定义了一个 `ListNode` 类型用于表示链表中的每一个节点。函数 `isPalindrome()` 接受指向链表头部的指针作为参数,并返回布尔值指示该链表是否构成回文序列。其中运用到了栈的数据结构来保存前一半链表的信息以便后续匹配验证[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dev_zyx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值