题目:
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?
题意:
给定一个链表,验证其是不是回文的,即从两头往中间元素是相等的。
思路:
由于需要空间复杂度是O(1)。如果没有这个要求使用O(n)的空间复杂度,可以直接使用一个栈将元素从头到尾入栈,那么出栈时就可以从尾到头依次出栈,然后比较从头到尾的链表元素与从栈中出来的从尾到头的元素是否相等。
代码如下:
/**
* 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 == NULL)return true;
stack<ListNode*>s;
ListNode* tmp = head;
while(tmp != NULL) {
s.push(tmp);
tmp = tmp->next;
}
while(!s.empty()) {
ListNode* node = s.top();
s.pop();
if(node->val != head->val)return false;
head = head->next;
}
return true;
}
};
但是现在要求是O(1)的空间复杂度,所以不能使用栈来装元素。可以采用翻转链表后一半元素的方法。比如原来元素是1->2->3->2->1,逆转后半部分后链表就是1->2->3->1->2,那么只要从后半部分的第一个元素以及前半部分的第一个元素开始往后遍历。
/**
* 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 == NULL || head->next == NULL)return true;
int count = 0;
ListNode* tmp = head;
while(tmp != NULL){
count++;
tmp = tmp->next;
}
int middle = count / 2;
tmp = head;
ListNode* last = NULL;
for(int i = 0; i < middle; i++) {
last = tmp;
tmp = tmp->next;
}
if(count % 2) {
last = last->next;
tmp = tmp->next;
}
tmp = reverseList(tmp);
while(tmp != NULL) {
if(head->val != tmp->val)return false;
head = head->next;
tmp = tmp->next;
}
return true;
}
ListNode* reverseList (ListNode * now) {
ListNode* past = NULL;
ListNode* future = now;
while(future != NULL) {
future = future->next;
now->next = past;
past = now;
now = future;
}
return past;
}
};