💥【每天学习亿点点系列】——单链表OJ题
1. 链表的回文结构
题目
方法一:翻转后半段,与前半段对比
如果在你写完链表寻找中间节点,和链表翻转后再来写这题,就选的很轻松,因为这就是那两题的考察。
你想想是不是,如果你找到中间节点,再翻转一下后半部分,与前半部分一对比,如果都相等则是回文。
代码实现
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
bool chkPalindrome(ListNode* A) {
// write code here
struct ListNode* slow,*fast,*pre,*cur,*next;
if(fast==NULL||fast->next==NULL)
{
return true;
}
slow=fast=A;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
}
pre=slow;
cur=slow->next;
next=cur->next;
pre->next=NULL;
while(cur)
{
cur->next=pre;
pre=cur;
cur=next;
if(next!=NULL)
{
next=next->next;
}
}
while(A&&pre)
{
if(A->val!=pre->val)
{
return false;
}
A=A->next;
pre=pre->next;
}
return true;
}
};
方法二:数组法(不推荐)
当看到回文链表是对称的时候,我们是不是就会想:能不能一个指针指向头,一个指向尾,然后逐个对比了,可这是单链表,往前面走不好走。那怎么办了?
既然这题里面已经告诉我们链表最长为900个节点,那我们不防创建一个900个空间的数组,然后把每一个节点的val存放进去,用数组来实现之前的想法就很容易实现了,但这样做是有些不好的,因为这是链表题。
代码实现
class PalindromeList {
public:
bool chkPalindrome(ListNode* A) {
// write code here
int a[900] = {0};
ListNode* cur = A;
int n = 0;
//保存链表元素
while(cur)
{
a[n++] = cur->val;
cur = cur->next;
}
//判断数组是否为回文结构
int begin = 0, end = n-1;
while(begin < end)
{
if(a[begin] != a[end])
return false;
++begin;
--end;
}
return true;
}
};
2.相交链表
题目
解决方法
如果链表相交,那么肯定其中某个节点之后的next节点是同等的,我们只要找出那个节点,并返回就行了。但问题是怎么找了,这里大家肯定要想逐个往后遍历,然后判断是否相等,但你要注意一个问题,这儿它的链表长度是不相等的,所以会有误差,这是一个注意点;第二个注意点,你要注意他们尾节点之后的next都等于NULL,这也是一个问题;第三个注意点,这里就要涉及如何解决第一个注意点了:那就是将两个链表从同样的长度处出发,但这时要注意,有可能你出发时的那个节点就是相遇节点。
代码实现
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
int sizeA=0;
int sizeB=0;
struct ListNode* curA=headA;
struct ListNode* curB=headB;
int gap=0;
while(curA)
{
sizeA++;
curA=curA->next;
}
while(curB)
{
sizeB++;
curB=curB->next;
}
curA=headA;
curB=headB;
if(sizeA>sizeB)
{
gap=sizeA-sizeB;
while(gap--)
{
curA=curA->next;
}
if(curA==curB) //注意万一你移完gap步之后就是相交节点
{
return curA;
}
}
else
{
gap=sizeB-sizeA;
while(gap--)
{
curB=curB->next;
}
if(curA==curB) //同上
{
return curA;
}
}
while(curA)
{
if(curA->next==curB->next&&curA->next!=NULL) //这种情况要注意
{
return curA->next;
}
else
{
curA=curA->next;
curB=curB->next;
}
}
return NULL;
}
3.环形链表
解决方法
说实话当看到最初看到这题时,这一脸迷茫的,初次做这题确实很难想出解决方法。这题解决的最好方法就是用快慢指针来解决,让快指针走两步,慢指针走一步,最后在环里面两者肯定会相遇,因为他们两一直是相差一步,又由于圆的定宽行,你一步步的追,最后一定会相遇。
代码实现
Node* slow = head;
Node* fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
return true;
}
return false;