来自牛客的一道OJ题:链表的回文结构_牛客题霸_牛客网 (nowcoder.com)
问题描述:
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文
结构。
给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于
900。
示例1:
1->2->2->1
返回:true
示例二:
1->2->3->4->5->6->7
返回:false
问题分析:
判断是否为回文结构, 具体有两种解法:
1.先找到链表的中间节点,将中间到链表尾的节点全部逆序,并将中间节点作为一个新链表的头,
将原链表和新链表的节点进行一一比较,直到新链表结束,如果每个节点对应的val都相等,那么
此链表为回文结构。
2.这种方法相较与上述方法思想更简单,但时间复杂度可能更高一点,将整个原链表进行逆序,
用一个新节点赋值逆序后的头节点,将原链表和新链表的节点进行一一比较,直到链表结束,
如果每个节点对应的val都相等,那么此链表为回文结构。
代码实现:
方法一:
1.先找到链表的中间节点(快慢指针法)
struct ListNode* middleNode(struct ListNode* head)
{
struct ListNode* slow = head;
struct ListNode* fast = head;
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
2.将中间到链表尾的节点全部逆序(用链表头插)
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* cur=head;
struct ListNode* newhead =NULL;
while(cur)
{
struct ListNode* next =cur->next;
//头插
cur->next =newhead;
newhead=cur;
//迭代
cur =next;
}
return newhead;
}
3.并将中间节点作为一个新链表的头,将原链表和新链表的节点进行一一比较,直到新链表结束。
bool chkPalindrome(ListNode* A)
{
struct ListNode* mid = middleNode(A);
struct ListNode* rHead = reverseList(mid);
struct ListNode* curA = A;
struct ListNode* curR = rHead;
while(curA && curR)
{
if(curA->val != curR->val)
{
return false;
}
else
{
curA = curA->next;
curR = curR->next;
}
}
return true;
}
方法二:
1.将整个原链表进行逆序,用一个新节点赋值逆序后的头节点。
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* cur=head;
struct ListNode* newhead =NULL;
while(cur)
{
struct ListNode* next =cur->next;
//头插
cur->next =newhead;
newhead=cur;
//迭代
cur =next;
}
return newhead;
}
struct ListNode* rHead = reverseList(A);
2.将原链表和新链表的节点进行一一比较,直到链表结束。
bool chkPalindrome(ListNode* A)
{
//struct ListNode* mid = middleNode(A);
struct ListNode* rHead = reverseList(A);
struct ListNode* curA = A;
struct ListNode* curR = rHead;
while(curA && curR)
{
if(curA->val != curR->val)
{
return false;
}
else
{
curA = curA->next;
curR = curR->next;
}
}
return true;
}
整体代码:
方法一:
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* cur=head;
struct ListNode* newhead =NULL;
while(cur)
{
struct ListNode* next =cur->next;
//头插
cur->next =newhead;
newhead=cur;
//迭代
cur =next;
}
return newhead;
}
struct ListNode* middleNode(struct ListNode* head)
{
struct ListNode* slow = head;
struct ListNode* fast = head;
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
class PalindromeList {
public:
bool chkPalindrome(ListNode* A)
{
struct ListNode* mid = middleNode(A);
struct ListNode* rHead = reverseList(mid);
struct ListNode* curA = A;
struct ListNode* curR = rHead;
while(curA && curR)
{
if(curA->val != curR->val)
{
return false;
}
else
{
curA = curA->next;
curR = curR->next;
}
}
return true;
}
};
方法二:
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* cur=head;
struct ListNode* newhead =NULL;
while(cur)
{
struct ListNode* next =cur->next;
//头插
cur->next =newhead;
newhead=cur;
//迭代
cur =next;
}
return newhead;
}
struct ListNode* middleNode(struct ListNode* head)
{
struct ListNode* slow = head;
struct ListNode* fast = head;
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
class PalindromeList {
public:
bool chkPalindrome(ListNode* A)
{
//struct ListNode* mid = middleNode(A);
struct ListNode* rHead = reverseList(A);
struct ListNode* curA = A;
struct ListNode* curR = rHead;
while(curA && curR)
{
if(curA->val != curR->val)
{
return false;
}
else
{
curA = curA->next;
curR = curR->next;
}
}
return true;
}
};