第五道、#234. 回文链表
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
1、借助栈检查回文链表
(1)将链表里的所有val值入栈操作
(2)然后再从头到尾遍历链表
(3)比较其与栈顶元素是否相等(因为栈的数据结构特征,后来者据上此时比较的元素刚好是链表的首部和尾部比较)
/**
* 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) {
stack<int> st; //存储val
ListNode* p=head;
while(p){ //存数据入栈
st.push(p->val);
p = p->next;
}
p = head;
while(p){ //遍历链表元素
if(p->val != st.top()) //检测回文性
return false;
else{
p = p->next; //指向下一个节点
st.pop(); //出栈
}
}
return true;
}
};
2、双指针法
(1)分别用快慢指针指向头部
(2)遍历链表,慢指针每次跳到下一个,快指针跳到下一个的下一个
(3)慢指针遍历的时候同时反转链表的转向,方便后面检验回文性
(4)当链表长度为奇数时记得将slow向后跳一个,去除中间项
/**
* 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 1; //切忌!!!!!!先考虑特殊情况
ListNode* slow = head; //慢指针
ListNode* fast = head; //快指针
ListNode* p = head;
ListNode* pre = NULL;
while(fast && fast->next){
p = slow;
slow = slow->next;
fast = fast->next->next;
p->next = pre; //反转链表
pre = p;
}
if(fast) // 如果链表节点为奇数个,跳过中间节点
slow = slow->next;
while(p){
if(p->val != slow->val) //从中间分别向两边遍历,检验回文性
return false;
slow = slow->next;
p = p->next;
}
return true;
}
};