题目描述:
编写一个函数,检查输入的链表是否是回文的。
解题思路:
本人的思路是,首先找到链表的中间结点的前一个结点,如果链表是偶数个,则直接分开成两个链表,然后将前一个链表逆置再依次判断结点的大小是否相等。如果链表结点是奇数个,直接将中间结点删去,该就变成 为偶数个,按照上面的方法继续求解。
代码:
// 该方法找的不是中间值,而是中间值的前一个,如果是偶数则返回前一个中间值
//如果是奇数,则删掉中间值并返回前一个值
struct ListNode* getMid(struct ListNode* head)
{
struct ListNode* slow = head;
struct ListNode* fast = head;
struct ListNode* pre = slow;
while(fast && fast->next)
{
pre = slow;
slow = slow->next;
fast = fast->next->next;
if(fast!=NULL && fast->next==NULL)
{
pre->next = slow->next;
}
}
return pre;
}
bool isPalindrome(struct ListNode* head){
if(head==NULL)
{
return true;
}
// 获取前一个链表的尾结点
struct ListNode* mid = getMid(head);
// 获取后一个链表的头结点
struct ListNode* behind = mid->next;
//将前一个链表的尾结点置空
mid->next = NULL;
struct ListNode* pre = NULL;
struct ListNode* p_next;
while(head!=NULL)
{
p_next = head->next;
head->next = pre;
pre = head;
head = p_next;
}
while(pre && behind)
{
if(pre->val==behind->val)
{
pre = pre->next;
behind = behind->next;
}
else
{
return false;
}
}
return true;
}
然而看了解析发现,无需判断链表是否为偶数还是奇数,且无需把分开后的前一个链表的最后链接置为空。后一个链表的头结点是链表的中间结点 mid,且此解不是将前一个链表逆置,而是将后一个链表逆置,逆置后前一个链表的最后一个结点指向的是后一个链表的最后一个结点,这样链表无论是偶数个元素还是奇数个,如果是回文链表,每一个元素的值都还是相同的。
代码
// 获取中间值,如果是偶数返回第二个中间值
struct ListNode* getMid(struct ListNode* head)
{
struct ListNode* slow = head;
struct ListNode* fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
// 逆置函数
struct ListNode* reverse(struct ListNode* head)
{
struct ListNode* newHead = NULL;
while(head)
{
struct ListNode* h_next = head->next;
head->next = newHead;
newHead = head;
head = h_next;
}
return newHead;
}
bool isPalindrome(struct ListNode* head){
if(head==NULL)
{
return true;
}
struct ListNode* mid = getMid(head);
struct ListNode* behind = reverse(mid);
while(behind)
{
if(head->val==behind->val)
{
head = head->next;
behind = behind->next;
}
else
{
return false;
}
}
return true;
}