请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
满足进阶要求,将后半段链表(或前半段)反转,再各自遍历。在找链表中点时,采用快慢指针的方法。注意的是,当链表节点数为奇数时,slow指向链表正中间节点;为偶数时,slow指向链表右侧第一个节点。
ListNode* findMiddle(ListNode* head)
{
if(head == nullptr || head->next == nullptr)
return head;
ListNode* fast = head;
ListNode* slow = head;
while(fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
}
return slow;//若节点数为奇数,返回的是中间节点,否则为中间靠右节点
}
接下来的判断回文链表函数就很容易实现了。链表分为head和middle两段。有一个小细节,假设链表为1->2->3->4->5->6->7,分割后变为1->2->3->4<-5<-6<-7。而假设链表为1->2->3->4->5->6,分割后变为1->2->3->4-<5-<6,可见middle段比head段少一个节点。所以为了方便起见,分别遍历判断时while的循环条件应为middle != nullptr。
bool isPalindrome(ListNode* head)
{
if(head == nullptr || head->next == nullptr)
return true;
ListNode* middle = findMiddle(head);
middle = reverse(middle);
while(middle)
{
if(middle->val != head->val)
return false;
middle = middle->next;
head = head->next;
}
return true;
}