题目描述
题目分析
1.回文结构是指一个序列或字符串从前往后读或从后往前读都是相同的。
2.时间复杂度为O(n),说明循环只能有一层;空间复杂度为O(1),说明不能额外的申请空间。
3.链表的结点最多不会超过900个。
思路 1
思路1:
创建新的数组,遍历原链表,将链表结点中的值放入数组,在数组中判断链表是否为回文结构。
画图解释 1
创建新的数组,遍历原链表,将链表结点中的值放入数组
定义两个指针left和right,left从前往后遍历,right从后往前遍历,比较left和right的值是否相等,当left<right的时候,如果left的值不等于right的值,说明不是回文结构。
完整代码
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
bool chkPalindrome(ListNode* A)
{
// write code here
int arr[900]={0};
ListNode* pcur=A;
int i=0;
while(pcur)
{
arr[i++]=pcur->val;
pcur=pcur->next;
}
//i即结点个数
//找中间结点,判断是否为回文数字
int left=0;
int right=i-1;
while(left<right)
{
if(arr[left]!=arr[right])
{
//不是回文结构
return false;
}
left++;
right--;
}
return true;
}
};
思考:若这里没有对链表的结点个数进行限制,这种思路肯定是不行的!因为不满足时间复杂度 为O(n),空间复杂度为O(1)。而且该思路只能在牛客上面通过,如果换成力扣,无法通过。因为牛 客平台对时间复杂度和空间复杂度的校验没有力扣平台的那么严格。
思路 2
找链表的中间结点(利用快慢指针);将中间结点之后的链表反转。
画图解释 2
利用快慢指针找链表的中间结点,此时slow指向的是中间结点。
将中间结点之后的链表进行反转
定义两个指针left和right,left从前往后遍历,right从后往前遍历,判断left和right是否相等。
完整代码
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
ListNode*findMidNode(ListNode* phead)
{
ListNode*slow=phead;
ListNode*fast=phead;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
}
return slow;
}
ListNode*reverseList(ListNode*phead)
{
ListNode*n1,*n2,*n3;
n1=NULL,n2=phead,n3=n2->next;
while(n2)
{
n2->next=n1;
n1=n2;
n2=n3;
if(n3)
n3=n3->next;
}
return n1;
}
bool chkPalindrome(ListNode* A)
{
// write code here
//找中间结点
ListNode*mid=findMidNode(A);
//根据中间节点反转后面的链表
ListNode*right=reverseList(mid);
//从原链表和反转链表比较结点的值
ListNode*left=A;
while(right)
{
if(left->val!=right->val)
{
return false;
}
left=left->next;
right=right->next;
}
return true;
}
};