Given a singly linked list, determine if it is a palindrome.
Follow up:
Could you do it in O(n) time and O(1) space?
一开始的思路就是把链表的节点值用vector存起来,再首++尾--进行判断
代码如下
/**
* 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 true;
vector<int> p;
while(head){
p.push_back(head->val);
head = head->next;
}
int j = p.size() - 1;
for (int i=0;i<j;i++,j--){
if(p[i] != p[j])
return false;
}
return true;
}
};
但是这样的话就没有做到O(1)的空间复杂度
那么我们就想,上面一种方法是首尾向中靠近判断,那我们把后半段翻转过来,
如图所示,最后p和q指针同时向后移动,遇到不相等的就返回false
/**
* 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) {
//如果链表为空或者只有一个元素就返回true
if (!head || !head->next)
return true;
//用来定位到链表的中间
ListNode* slow = head;
ListNode* fast = head;
while(fast->next && fast->next->next){
slow = slow->next;
fast = fast->next->next;
}
//现在slow就指向链表的中间部分
ListNode*middle = slow,*temp;
//curr指向后半段的第一个节点
ListNode* curr = middle->next;
//这里把前半段和后半段分开
middle->next = NULL;
while(curr){
temp = curr;
curr = curr->next;
temp->next = middle->next;
middle->next = temp;
}
middle = middle->next;
while(middle){
if(head->val != middle->val)
return false;
head = head->next;
middle = middle->next;
}
return true;
}
};
这样就满足O(1)的空间复杂度了,不过时间比第一种方法慢了一点