1,题目要求
Given a singly linked list, determine if it is a palindrome.
Example 1:
Input: 1->2
Output: false
Example 2:
Input:1->2->2->1
Output: true
Follow up:
Could you do it in O(n) time and O(1) space?
给出一个单链表,确定它是否是回文。
跟进:
你能在O(n)时间和O(1)空间做吗?
2,题目思路
对于这道题,是判断一个链表是否构成回文形式。
一般来说,判断一个字符串或者一个数组是不是回文比较简单,直接两端向中间依次进行比较即可,但是链表是个比较特殊的形式,尤其是题目中所规定的单链表。
因此,对于这个问题,我们有两种解决思路:
一种比较直观,直接对链表进行遍历,将其中所有的节点的值保存在一个数组中,然后按照数组的标准来实现回文序列的判断。
第二种方法,则是直接在链表上进行操作。
由之前的快慢指针法我们可以得知,当快指针到达尾部时,慢指针恰好走到了链表的中间位置。再由链表反转可得,我们只需要将后半段的链表进行反转,然后再依次对节点的值进行判断,也可以实现回文判断。这种方法不需要辅助内存。
3,代码实现
1,辅助数组
int x = []() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
return 0;
}();
class Solution {
public:
bool isPalindrome(ListNode* head) {
if(head == nullptr || head->next == nullptr)
return true;
vector<int> listNum;
while(head!= nullptr)
{
listNum.push_back(head->val);
head = head->next;
}
int n = listNum.size();
for(int i = 0;i< n/2;i++){
if(listNum[i]!= listNum[n-1-i])
return false;
}
return true;
}
};
2,反转后半链表
class Solution {
public:
bool isPalindrome(ListNode* head) {
ListNode* slow = head, *fast = head;
while(fast!=NULL && fast->next!=NULL)
{
slow = slow->next;
fast = fast->next->next;
}
if(fast!= NULL) //说明节点的个数为奇数个
slow = slow->next; //目的只是为了使得slow找到中间靠后一个的节点
slow = reverseList(slow);
fast = head;
while(slow!=NULL)
{
if(slow->val != fast->val)
return false;
slow = slow->next;
fast = fast->next;
}
return true;
}
public:
//反转链表
ListNode* reverseList(ListNode* node){
ListNode* pre = NULL;
while(node!=NULL){
ListNode* next = node->next;
node->next = pre;
pre = node;
node = next;
}
return pre;
}
};