234 Palindrome Linked List 回文链表

本文介绍两种检测链表是否为回文的方法。一种使用栈存储元素进行比较,另一种通过翻转链表后半部分来判断。这两种方法均能达到O(n)时间复杂度。

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

请检查一个链表是否为回文链表。

进阶:
你能在 O(n) 的时间和 O(1) 的额外空间中做到吗?

详见:https://leetcode.com/problems/palindrome-linked-list/description/

Java实现:

方法一:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isPalindrome(ListNode head) {
        //0个节点或是1个节点
        if(head==null||head!=null&&head.next==null){
            return true;
        }
        ListNode slow=head;
        ListNode fast=head;
        Stack<Integer> stk=new Stack<Integer>();
        stk.push(head.val);
        while(fast.next!=null&&fast.next.next!=null){
            slow=slow.next;
            fast=fast.next.next;
            stk.push(slow.val);
        }
        //链表长度为偶数
        if(fast.next!=null){
            slow=slow.next;
        }
        while(slow!=null){
            int tmp=stk.pop();
            if(slow.val!=tmp){
                return false;
            }
            slow=slow.next;
        }
        return true;
    }
}

方法二:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isPalindrome(ListNode head) {
        //0个节点或是1个节点
        if(head==null||head!=null&&head.next==null){
            return true;
        }
        ListNode slow=head;
        ListNode fast=head;
        ListNode first=null;
        while(fast!=null&&fast.next!=null){
            first=slow;
            slow=slow.next;
            fast=fast.next.next;
        }
        fast=first.next;
        first.next=null;
        ListNode pre=null;
        ListNode next=null;
        while(fast!=null){
            next=fast.next;
            fast.next=pre;
            pre=fast;
            fast=next;
        }
        first=head;
        fast=pre;
        while(first!=null&&fast!=null){
            if(first.val!=fast.val){
                return false;
            }
            first=first.next;
            fast=fast.next;
        }
        return true;
    }
}

C++实现:

方法一:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if(head==nullptr||head->next==nullptr)
        {
            return true;
        }
        ListNode *slow=head;
        ListNode *fast=head;
        stack<int> stk;
        stk.push(head->val);
        while(fast->next&&fast->next->next)
        {
            slow=slow->next;
            fast=fast->next->next;
            stk.push(slow->val);
        }
        if(!fast->next)
        {
            stk.pop();
        }
        while(slow->next)
        {
            slow=slow->next;
            int tmp=stk.top();
            if(slow->val!=tmp)
            {
                return false;
            }
            stk.pop();
        }
        return true;
    }
};

方法二:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if(!head||!head->next)
        {
            return true;
        }
        ListNode *slow=head;
        ListNode *fast=head;
        ListNode *first=nullptr;
        while(fast&&fast->next)
        {
            first=slow;
            slow=slow->next;
            fast=fast->next->next;
        }
        fast=first->next;
        first->next=nullptr;
        ListNode *pre=nullptr;
        ListNode *next=nullptr;
        while(fast)
        {
            next=fast->next;
            fast->next=pre;
            pre=fast;
            fast=next;
        }
        first=head,fast=pre;
        while(first&&fast)
        {
            if(first->val!=fast->val)
            {
                return false;
            }
            first=first->next;
            fast=fast->next;
        }
        return true;
    }
};

参考:https://www.cnblogs.com/grandyang/p/4635425.html

转载于:https://www.cnblogs.com/xidian2014/p/8759212.html

<< 要判断一个单链表是否为回文结构(即正读反读都相同),常见的解决方案涉及以下几种思路: 1. **将元素存入数组**:先遍历整个链表,并把所有节点值保存到一维数组中;然后使用双指针法对这个数组进行检查,看其是否满足回文特性。 2. **反转后半部分链表并比较**: - 首先利用快慢指针找到中间位置。 - 接着从中间开始翻转后面那段链表。 - 最后再逐个对比前后两段链表中的对应结点数据域内容是否相等即可得出结论。 这种方法的优点在于不需要额外的空间开销用于存储节点值副本,在原地完成判定操作。 下面是采用第二种方案的具体 C++ 实现代码示例: ```cpp #include <iostream> using namespace std; struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(nullptr) {} }; // 辅助函数:翻转给定的链表, 并返回新的头指针. ListNode* reverseList(ListNode* head){ if (!head || !(head->next)) return head; // 如果链表为空或只有一个节点,则直接返回 ListNode *prev = nullptr,*curr=head,*nxt=nullptr; while(curr !=nullptr){ nxt= curr -> next ; curr -> next = prev ; prev = curr ; curr=nxt; } return prev; } bool isPalindrome(ListNode* head) { if(head == nullptr || head->next == nullptr) return true; // 使用快慢指针定位中心点 ListNode* slow = head; ListNode* fast = head; while(fast && fast->next){ slow = slow->next; fast = fast->next->next; } // 对于奇数长度的列表, 中间那个单独元素不用考虑, // 所以我们让slow再前进一步跳过它 if (fast!=nullptr) { slow = slow->next; } // 反转右半边子链表 ListNode* right_half_head = reverseList(slow); // 检查左右两边是否完全一致 bool result=true; for(auto pL = head,pR=right_half_head;pR!=nullptr;pL=pL->next,pR=pR->next){ if(pL->val !=pR->val){ result=false; break; } } // 将右侧恢复成原来的样子(可选步骤取决于应用需求). reverseList(right_half_head); return result; } int main() { // 构建测试用例 /* 创建如下所示的一个简单例子: 1 -> 2 -> 3 -> 2 -> 1 这显然是一个回文链表. */ ListNode n5{1}; ListNode n4{2,&n5}; ListNode n3{3,&n4}; ListNode n2{2,&n3}; ListNode n1{1,&n2}; cout << "Testing palindrome linked list..." << endl; cout << ((isPalindrome(&n1))? "Yes" :"No") <<endl; } ``` 这段程序首先定义了一个辅助性的`reverseList()` 函数来帮助我们在必要时能够很容易地逆转某个特定区间的链接序列。核心逻辑是在 `isPalindrome ()` 方法里执行了上述提到过的第二条策略——借助两个速度不同的游标去寻找分割点、接着调换下半截的数据流向以便前半部做匹配校验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值