思路一:
最容易想到的,把遍历过得结点放进栈中,然后利用栈的后进先出的特性逐个和原链表比较是否相同
class Solution {
public:
bool isPalindrome(ListNode* head) {
stack<ListNode*>stack;
ListNode *p=head;
if(p==NULL||p->next==NULL)
return true;
while(p){
stack.push(p);
p=p->next;
}
while(!stack.empty()){
ListNode *vall=stack.top();
stack.pop();
if(head->val!=vall->val)
return false;
head=head->next;
}
return true;
}
};
//只有确定head->next!=NULL才能取用head=head->next,否则会报错
思路二
其实也不算思路二,只是一个改进算法,我们可以先遍历一半,把这一半放进栈中,然后再让指针继续遍历,这时候再和出栈元素作对比,至于如何确定一半,那就利用快慢指针,当快指针到达最后,慢指针到达一半,当然若是偶数,还得让short向前挪一步
如果fast->next->next=NULL,就说明是奇数
如果fast->next=NULL就说明是偶数
Stack<ListNode> stack=new Stack<>();
ListNode slow=head;
ListNode fast=head;
if(fast==null||fast.next==null)//0个节点或是1个节点
return true;
stack.push(slow);
while(fast.next!=null&&fast.next.next!=null)
{
fast=fast.next.next;
slow=slow.next;
stack.push(slow);
}
if(fast.next!=null)//链表长度为偶数
slow=slow.next;
ListNode cur=slow;
while(cur!=null)
{
if(cur.val!=stack.pop().val)
return false;
cur=cur.next;
}
return true;
第三种:利用慢指针的反向遍历链表的反向遍历也可以说成反向输出,改变链表本身,时间可能会慢,但是空间小,基本不改变
class Solution {
public:
bool isPalindrome(ListNode* head) {
if(head==NULL||head->next==NULL)
return true;
ListNode* slow=head;
ListNode* fast=head;
while(fast->next!=NULL&&fast->next->next!=NULL){
slow=slow->next;
fast=fast->next->next;
}
slow->next=reverseList(slow->next);
slow=slow->next;
while(slow!=NULL){
if(head->val!=slow->val)
return false;
head=head->next;
slow=slow->next;
}
return true;
}
ListNode* reverseList(ListNode* head) {
ListNode* pre=NULL;
ListNode* next=NULL;
while(head!=NULL){
next=head->next;
head->next=pre;
pre=head;
head=next;
}
return pre;
}
};