题目一:
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead)
{
if(pHead==NULL&&pHead->next==NULL) return pHead;
ListNode* pre=NULL; //可能用到的当前结点的前驱指针
ListNode* now=pHead; //当前处理结点指针
ListNode* circP=NULL; //循环重复结点的工具指针
while(now!=NULL)
{
if(now->next!=NULL&&now->next->val==now->val) //当前结点和下个结点重复
{ //可能在第一个结点就出现重复
circP=now->next; //用工具指针去重
while(circP!=NULL&&circP->val==now->val)
{
circP=circP->next;
} //找到不重复的下个节点
if(now==pHead) //当前结点是头节点也就是在链表头就
pHead=circP; //出现重复
else //中间部分出现重复
pre->next=circP;
now=circP; //可能出现4->4->5->5之类的连续重
} //复情况
else
{
pre=now; //当链表头部的重复去除掉后,在处理
now=now->next; //中间部分的时候需要保留前驱结点指针
}
}
return pHead;
}
};
题目二:
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(pHead==NULL||pHead->next==NULL) return NULL; //没有环的情况,同时确保p和q有效
ListNode* p=pHead->next->next;
ListNode* q=pHead->next;
while(p!=NULL&&p->next!=NULL&&p!=q)
{
p=p->next->next;
q=q->next;
}
if(p==NULL||p->next==NULL) return NULL; //没有环
p=pHead;
while(p!=q)
{
p=p->next;
q=q->next;
}
return p;
}
};
图解:
快指针以较满指针2倍的步率向前移动,相遇在红色标注处,假设环前的长度为L,环以顺时针方向,相遇点距离环的入口点的距离为m,环中剩余长度为n,则有:
所以:
所以接下来让快指针回到头节点,以相同的步率前进,则再次相遇点一定在环的入口。