请判断一个链表是否为回文链表。
示例 1:
输入: 1->2 输出: false
示例 2:
输入: 1->2->2->1 输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
这道题让我们判断一个链表是否为回文链表,那么我们首先需要找到链表的中点,这个可以用快慢指针来实现,我们使用快慢指针找中点的原理是fast和slow两个指针,每次快指针走两步,慢指针走一步,等快指针走完时,慢指针的位置就是中点。我们还需要用栈,每次慢指针走一步,都把值存入栈中,等到达中点时,链表的前半段都存入栈中了,由于栈的后进先出的性质,就可以和后半段链表按照回文对应的顺序比较了。代码如下:
c++代码如下:
/**
* 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; //注意判断的顺序,不能出错
ListNode* slow=head;
ListNode* fast=head; //
stack<int> a; //建立一个堆栈
a.push(slow->val);
while(fast->next && fast->next->next)
{
fast=fast->next->next;
slow=slow->next;
a.push(slow->val);
}
if(!fast->next) a.pop();
while(slow->next)
{
slow=slow->next;
int temvalue=a.top(); a.pop();
if(temvalue != slow->val) return false;
}
return true;
}
};
这道题的让我们用O(1)的空间,那就是说我们不能使用stack了,那么如果代替stack的作用呢,用stack的目的是为了利用其后进先出的特点,好倒着取出前半段的元素。那么现在我们不用stack了,如何倒着取元素呢。我们可以在找到中点后,将后半段的链表翻转一下,这样我们就可以按照回文的顺序比较了,c++参见代码如下:(ps:这个链表的代码翻转部分总感觉有点累赘,以后有时间要改进一下)
/**
* 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;
ListNode *slow = head, *fast = head;
while (fast->next && fast->next->next) {
slow = slow->next;
fast = fast->next->next;
}
slow=slow->next;
if(!slow->next)
{
if(slow->val == head->val)
return true;
else return false;
}
ListNode* cur=slow->next;
slow->next=NULL;
while (cur->next) { //将slow后面的链表反转
ListNode* tem=cur->next;
cur->next=slow;
slow=cur;
cur=tem;
}
cur->next=slow;
while(cur)//判断
{
if(cur->val == head->val)
{
cur=cur->next;
head=head->next;
}
else return false;
}
return true;
}
};