【程序员面试金典】请编写一个函数,检查链表是否为回文。

本文介绍了一种使用栈和队列来判断链表是否为回文的方法。通过遍历链表,将节点值同时压入栈和队列,并在之后逐一对比两者头部和顶部的元素来验证链表是否对称。

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

题目描述

请编写一个函数,检查链表是否为回文。

给定一个链表ListNode* pHead,请返回一个bool,代表链表是否为回文。

测试样例:

{1,2,3,2,1}
返回:true
{1,2,3,2,3}
返回:false

生成一个栈和队列,再取值比较。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Palindrome {
public:
    bool isPalindrome(ListNode* pHead) {
        // write code here
        stack<int> S;
        queue<int> Q;
        int number = 0;
        while(pHead != NULL)
        {
            S.push(pHead->val);
            Q.push(pHead->val);
            pHead->pHead->next;
            number++;
        }
        //作比较
        for(int i = 0; i < number; i++)
        {
            if(Q.front() == S.top())
            {
                S.pop();
                Q.pop();
            }
            else
            {
                return false;
            }
        }
        return true;
        
    }
};

 

### 单向链表是否回文的检测 为了实现一个时间复杂度为 \( O(n) \),额外空间复杂度为 \( O(1) \) 的算法来判断单向链表是否回文结构,可以采用以下策略: #### 方法概述 1. 使用 **快慢指针** 找到链表的中点位置。当快指针到达链表末尾时,慢指针正好位于链表中间[^3]。 2. 将链表的后半部分就地反转。 3. 同时从链表头部和已反转的后半部分开始逐一对比节点值,直到发现不同或完成对比。 4. 如果需要保持原始链表不变,则可以在最后恢复链表。 以下是具体的 C++ 实现代码: ```cpp #include <iostream> struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(nullptr) {} }; // 反转链表的功能函数 ListNode* reverseList(ListNode* head) { ListNode* prev = nullptr; ListNode* curr = head; while (curr != nullptr) { ListNode* tempNext = curr->next; curr->next = prev; prev = curr; curr = tempNext; } return prev; } // 判断链表是否回文 bool isPalindrome(ListNode* A) { if (!A || !A->next) return true; // Step 1: 使用快慢指针找到链表中点 ListNode *slow = A, *fast = A; while (fast && fast->next) { slow = slow->next; fast = fast->next->next; } // Step 2: 反转后半部分链表 ListNode* secondHalfStart = reverseList(slow); // Step 3: 对比前后两部分链表 ListNode* firstPosition = A; ListNode* secondPosition = secondHalfStart; bool result = true; while (secondPosition != nullptr) { if (firstPosition->val != secondPosition->val) { result = false; break; } firstPosition = firstPosition->next; secondPosition = secondPosition->next; } // Step 4: 恢复链表(可选) reverseList(secondHalfStart); return result; } ``` --- ### 双向链表是否回文的检测 对于双向链表而言,由于每个节点不仅有 `next` 还有 `prev` 指针,因此可以直接利用这两个指针对称的特点来进行比较而无需修改原链表结构。 具体做法如下: 1. 遍历整个链表一次,记录下第一个节点到最后一个节点的所有值。 2. 使用双指针技术分别从前端和末端逐步向中心移动并逐一比较对应的值。 下面是基于上述思路的一个简单 C++ 实现版本: ```cpp #include <vector> using namespace std; struct DoublyListNode { int val; DoublyListNode* prev; DoublyListNode* next; DoublyListNode(int x): val(x), prev(NULL), next(NULL){} }; bool isDoublyLinkedListPalindrome(DoublyListNode* head){ vector<int> vals; // 收集所有的数值 DoublyListNode* current = head; while(current != NULL){ vals.push_back(current -> val); current = current -> next; } // 检查数组是否是回文序列 for(size_t i=0;i<vals.size()/2;++i){ if(vals[i]!=vals[vals.size()-1-i]){ return false; } } return true; } ``` --- ### 总结 以上两种方式均满足题目所要求的时间复杂度 \( O(n) \) 和空间复杂度 \( O(1) \)[^1][^2][^3] 。其中需要注意的是,在处理单向链表时我们通过改变链接方向实现了常数级的空间消耗;而对于双向链表则直接借助其天然具备的反向访问能力简化了操作流程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值