题解 | #链表的回文结构#
链表的回文结构
https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
/*
思路:将链表的节点逆置,然后得到的新链表与原链表进行比较,看是否相等,相等的话那么这个链表就具有回文结构
*/
/*
思路一:创建新的数组,遍历原链表,将链表节点中的值放入数组中,在数组中判断是否为回文结构
*/
// class PalindromeList {
// public:
// bool chkPalindrome(ListNode* A) {
// int arr[900]={0};
// ListNode *pcur=A;
// int i=0;
// while(pcur)//遍历原链表,pcur不能为空
// {
// //将链表中每个节点的值放到arr中
// arr[i]=pcur->val;
// i++;
// pcur=pcur->next;//换下一个节点
// }
// //i即节点的个数,因为我们的i一直在进行++操作
// //找中间节点,判断是否为回文数字
// int left=0;
// int right=i-1;//i是数组中数据的有效个数
// //我们比较left和right的下标的数字的大小,相等的话我们就让两个指针一直走,直到遍历整个数组
// while(left<right)
// {
// if(arr[left]!=arr[right])
// {
// //那么肯定不是回文结构
// return false;
// }
// right--;
// left++;
// }
// //说明是回文结构,因为已经跳出循环了
// return true;
// }
// };
//这道题我们注意:我们开辟了空间,arr[900]
//但是假如我们碰到的题没有对链表节点个数进行限制的话,那么这种思路的话肯定是不行的
//除此之外,该思路只能在牛客上通过,力扣是不行的
//思路二:反转链表
/*
1.找链表的中间节点(快慢指针)
2.将中间节点及中间节点之后的链表进行反转
此时我们的right和left就能接着后面进行比较了
*/
/*反转链表的思路:
创建三个指针,n1 n2 n3
解释下思路二:
一开始我们的n1是空指针,n2指向的是1,n3指向的是2
我们将n2的指向改变指向n1,然后1就指向了空指针1->NULL
然后我们将n1放到n2的位置,n2放到n3的位置,那么现在n1指向的是1,n2指向的是2,n3指向的是3
我们将n2的指向改变指向为n1 2->1->NULL
然后我们将n1放到n2的位置,n2放到n3的位置,那么现在n1指向的是2,n2指向的是3,n3指向的是4 我们将n2的指向改变指向为n1 3->2->1->NULL
然后我们将n1放到n2的位置,n2放到n3的位置,那么现在n1指向的是3,n2指向的是4,n3指向的是5 我们将n2的指向改变指向为n1 4->3->2->1->NULL
然后我们将n1放到n2的位置,n2放到n3的位置,那么现在n1指向的是4,n2指向的是5,n3指向的是走出去了 我们将n2的指向改变指向为n1 5->4->3->2->1->NULL
最后n1走到n2,n2走到n3 n2和n3都走出去了,现在的n1指向的是5的位置,那么现在的5就是新的头结点了
*/
class PalindromeList
{
public:
ListNode*findMidNode(ListNode* phead)//封装一个函数来找中间节点
{
//快慢指针
ListNode*slow=phead;
ListNode*fast=phead;
while(fast&&fast->next)//fast和fast下个节点不为空
{
slow=slow->next;//慢指针每次走一步
fast=fast->next->next;//快指针每次走两次
}
//那么此时的slow节点刚好指向了中间节点
return slow;
}
ListNode*reverseList(ListNode* phead)//封装一个函数来反转链表
{
ListNode*n1,*n2,*n3;
n1=NULL;
n2=phead;
n3=n2->next;
while(n2)//当n2为空的时候,那么此时的n1就指向的是反转后链表的头
{
n2->next=n1;
n1=n2;
n2=n3;
if(n3)//n3不能为空才能往下走,只要n3到空了,我们就没必要让n3继续走了
{
n3=n3->next;
}
}
//跳出循环 此时的n1就是反转后链表的头节点
return n1;
}
bool chkPalindrome(ListNode* A)
{
//1.找中间节点
ListNode*mid=findMidNode(A);//将链表A传过去
//2.根据中间节点反转后面的链表
ListNode*right=reverseList(mid);//将mid传过去,作为后半段头结点
//那么此时的right就是指向的是反转后链表的头结点
//3.从原链表和反转链表比较节点的值
ListNode*left=A;//让left赋值为头节点
//让right和left对应的指针进行一一比较
while(right)//我们以right为主,一但right遍历到空,我们就没必要进行比较了
{
if(left->val!=right->val)//那么就不是回文结构了
{
return false;
}
//走到这里就说明当前节点对应的大小是相等的,那么我们就进行下一对节点的比较
//让两个指针往后走
left=left->next;
right=right->next;
}
//跳出循环,那么此时的right已经为空了
//那么这个链表的结构就是回文结构了
return true;
}
};
查看5道真题和解析
