234.回文链表
解题思路
回文链表的话,就是第一个数和倒数第一个数相同,第二个数和倒数第二个数相同,一次类推,但是链表我们无法直接从最后一个节点开始从后往前推,因此对于判断是不是回文链表,首先我们需要找到链表的中间节点
1. 链表的中间节点
对于长度为奇数 的链表,正中间的节点就是中间节点。
对于长度为偶数 的链表,找正中间右边的节点。
举例如下:
对于链表
1->2->3->4->5
中间节点就是正中间的3。
对于链表
1->2->3->4->5->6
中间节点是正中间右边的4。
2.反转链表
随后对得到了中间节点之后的链表部分进行反转链表,也就是说:
奇数链表:
3->4->5反转为3<-4<-5,而另一边1->2->3
偶数链表
1->2->3->4,而另一边4<-5<-6。
3.回文链表判断
我们记反转后的头节点是head2。
同时得注意得到了反转之后的链表之后,进行回文判断的时候,判断条件当中应该是head2是否为空,如果判断条件当中是head的话,那么对于奇数情况,head要比head2多走一步,但这时候head2已经是空的了,就会出现问题(head2.val,空指针异常)。
如何得到链表的中间节点呢?
使用快慢指针法,让快慢指针同时指向head,快指针每次移动2步,慢指针每次移动1步,当快指针为null或者快指针的next为null时,此时满指针的所指就是中间节点。
代码
C++
cpp
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
//找到中间节点
ListNode* Getmidddle(ListNode* head)
{
ListNode* fast = head;
ListNode* slow = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
//反转中间节点之后的链表部分
ListNode* ReverseLink(ListNode* head)
{
ListNode* pre = NULL;
ListNode* cur = head;
ListNode* nxt = NULL;
while(cur)
{
nxt = cur->next;
cur->next = pre;
pre = cur;
cur = nxt;
}
return pre;
}
bool isPalindrome(ListNode* head) {
//得到中间节点
ListNode* middle = Getmidddle(head);
ListNode* head2 = ReverseLink(middle);
while(head2)
{
if(head->val != head2->val)
return false;
head = head->next;
head2 = head2->next;
}
return true;
}
};
python
python
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
# 找到中间结果,对于奇数,直接就是中间
# 对于偶数,则是中间的右边节点
def GetMiddleNode(self, head):
"""
:type head: Optional[ListNode]
:rtype: ListNode
"""
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
# 反转链表
# 反转从中间节点到原本链表之间的关系,比如1->2->3->4->5->6
# 反转后:1->2->3->4<-5<-6
def reverseLink(self, head):
"""
:type head: Optional[ListNode]
:rtype: ListNode
"""
pre, cur= None, head
while cur:
nxt = cur.next
cur.next = pre
pre = cur
cur = nxt
return pre
def isPalindrome(self, head):
"""
:type head: Optional[ListNode]
:rtype: bool
"""
#1. 找到中间节点
middle = self.GetMiddleNode(head)
#2. 反转链表
head2 = self.reverseLink(middle)
while head2:
if head.val == head2.val:
head = head.next
head2 = head2.next
else:
return False
return True
