【链表】判断回文链表
(1)将链表转化为数组进行比较
比较呆板的做法,空间复杂度为O(n)
。
class Solution {
public:
bool isPalindrome(ListNode* head) {
vector<int> arr;
ListNode* p = head;
while (p) {
arr.push_back(p->val);
p = p->next;
}
int n = arr.size();
for (int i = 0, j = n - 1; i < j; i++, j--) {
if (arr[i] != arr[j])
return false;
}
return true;
}
};
(2)递归
链表也具有递归性质,二叉树也不过是链表的衍生。
利用后序遍历的思想:
先保存头结点(left,全局变量),然后递归至最后(最深)的结点(right),然后比较left
和right
的值;如果相等,由递归栈返回上一层(也即right向左走),再操作left向右走,这样就实现了left和right的双向奔赴。
class Solution {
private:
ListNode* left_ = nullptr;
bool Traverse(ListNode* right) {
if (!right)
return true;
bool res = Traverse(right->next);
res = res && (left_->val == right->val);
left_ = left_->next;
return res;
}
public:
bool isPalindrome(ListNode* head) {
left_ = head;
return Traverse(head->next);
}
};
(3)优化递归
利用方法二,看似是没有使用到额外空间了,但实际上还有递归所带来的函数调用栈的开销,其空间复杂度也为O(n)
。
因此可以利用双指针的思想,找到链表的中间结点后,将其后面的结点反转。
using ListNodePtr = ListNode*;
class Solution {
private:
ListNode* Reverse(ListNode* head) {
ListNodePtr cur = head, pre = nullptr;
while (cur) {
ListNodePtr ne = cur->next;
cur->next = pre;
pre = cur;
cur = ne;
}
return pre;
}
public:
bool isPalindrome(ListNode* head) {
ListNodePtr fast = head, slow = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
if (fast)
slow = slow->next;
ListNodePtr left = head;
ListNodePtr right = Reverse(slow);
while (right) {
if (left->val != right->val)
return false;
left = left->next;
right = right->next;
}
return true;
}
};
本文作者:KeroltのBlog
本文链接:https://www.cnblogs.com/kerolt/p/links-judging-the-links-of-hui-hui-z1rsj1z.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步