C++ 回文链表

本文介绍了一种检查链表是否为回文的方法。通过遍历链表获取长度,并记录节点值,最后比较首尾节点值是否一致来判断链表是否为回文。

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

/**
请编写一个函数,检查链表是否为回文。
给定一个链表ListNode* pHead,
请返回一个bool,代表链表是否为回文。

**/

#include<iostream>
using namespace std;

struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};
class Palindrome {
public:
    bool isPalindrome(ListNode* pHead) {
        // write code here
        // 第一遍遍历链表,得到链表的长度
        ListNode *p1,*p2;
        p1=pHead;
        p2=pHead;
        int length=0;
        while(p1){
            length+=1;
            p1=p1->next;
        }
        int value[length];
        for(int i=0;i<length;i++){
            value[i]=p2->val;
            p2=p2->next;
        }
        for(int j=0;j<int(length/2);j++){
            if(value[j]!=value[length-j-1]){
                return false;
            }
        }
        return true;
    }
};

int main(){
    int a[5]={1,2,3,2,3};

    ListNode *pHead,*p;
    pHead=new ListNode(0);
    p=pHead;

    for(int i=0;i<5;i++){
        ListNode *new_node=new ListNode(a[i]);
        p->next=new_node;
        p=p->next;
    }
    Palindrome sol;
    bool result;
    result=sol.isPalindrome(pHead->next);

    cout<<result<<endl;

    return 0;
}

 

### 方法概述 为了满足 O(n) 的时间复杂度和 O(1) 的空间复杂度的要求,可以通过以下方式来实现判断单链表是否为回文: 1. **找到中间节点**:通过快慢指针法找出链表的中间位置。 2. **反转后半部分链表**:将链表的后半部分就地反转。 3. **对比前后两部分**:逐一对比前半部分和已反转后的后半部分中的节点值。 4. **恢复原链表(可选)**:如果需要保持原始链表不变,则再次反转后半部分。 以下是具体的 C++ 实现代码以及解释。 --- ### C++ 实现代码 ```cpp #include <iostream> using namespace std; // 定义链表节点结构体 struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(nullptr) {} }; // 找到链表的中间节点 (使用快慢指针) ListNode* findMiddle(ListNode* head) { ListNode* slow = head; ListNode* fast = head; while (fast && fast->next) { // 当快指针到达末尾时停止 slow = slow->next; // 慢指针每次移动一步 fast = fast->next->next; // 快指针每次移动两步 } return slow; // 返回中间节点 } // 反转链表的一部分 ListNode* reverseList(ListNode* head) { ListNode* prev = nullptr; ListNode* curr = head; while (curr != nullptr) { ListNode* nextTemp = curr->next; // 记录下一个节点 curr->next = prev; // 将当前节点指向前面的节点 prev = curr; // 移动prev到当前节点 curr = nextTemp; // 移动curr到下一个节点 } return prev; // 返回新的头节点 } // 判断链表是否为回文 bool isPalindrome(ListNode* head) { if (!head || !head->next) return true; // 如果为空或者只有一个节点则一定是回文 // Step 1: 找到中间节点并分割成两个子链表 ListNode* mid = findMiddle(head); // Step 2: 反转后半部分链表 ListNode* secondHalfStart = reverseList(mid); // Step 3: 对比前后两部分 ListNode* p1 = head; ListNode* p2 = secondHalfStart; bool result = true; while (p2 != nullptr) { // 遍历第二部分直到结束 if (p1->val != p2->val) { result = false; break; } p1 = p1->next; p2 = p2->next; } // Step 4: 还原链表(可选) reverseList(secondHalfStart); return result; } ``` --- ### 解决方案说明 上述解决方案的核心逻辑如下: - 使用快慢指针定位链表的中间节点[^1]。 - 就地反转链表的后半部分以减少额外的空间开销[^2]。 - 同时遍历链表的前半部分和已经反转过的后半部分,逐一比较对应的节点值[^3]。 - 若发现不匹配的情况立即返回 `false`;若整个过程未发现问题,则最终返回 `true`[^4]。 此方法的时间复杂度为 O(n),因为每个操作均只需一次完整的链表扫描即可完成。而由于只用了固定数量的变量作为辅助存储单元,因此空间复杂度达到了题目所要求的 O(1)。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值