1.判断单链表是否带环?若带环,求环的长度?求环的入口点?
1)链表是否带环,我们需要用快(走两步)慢(走一步)指针,如果慢的和快的相等则链表带环
bool ListCycl(Node* pHead)
{
if (pHead == NULL)
{
return fase;
}
Node* fast = pHead;
Node* slow = pHead;
while (fast)
{
fast = fast->next->next;
slow = slow->next;
if (slow == fast)
{
return true;
}
}
return false;
}
2)入口点
2.判断两个链表是否相交,若相交,求交点。(假设链表不带环)
int Check_Link(ListNode* pList1,ListNode* pList2)
{
//判断链表是否相交,查看其尾节点是否相同
ListNode* p1=pList1;
ListNode* p2=pList2;
if(p1==NULL||p2==NULL)
return -1;
while(p1->_next!=NULL)
{
p1=p1->_next;
}
while(p2->_next!=NULL)
{
p2=p2->_next;
}
if(p1==p2)
{
return 1; //相交
}
return 0;
}
ListNode* GetLinkNode(ListNode* pList1,ListNode* pList2)
{
//统计出两个链表的结点总数count1,count2
//让较长的链表走count1-count2步
//两个链表一起走直到相遇则返回相遇结点的地址
int cout1=0;
int cout2=0;
assert(pList1);
assert(pList2);
ListNode* p1=pList1;
ListNode* p2=pList2;
while(p1)
{
cout1+=1;
p1=p1->_next;
}
while(p2)
{
cout2+=1;
p2=p2->_next;
}
p1=pList1;
p2=pList2;
int num=cout1-cout2;
if(num>0)
{
while(num--)
{
p1=p1->_next;
}
if(p1!=p2)
{
p1=p1->_next;
p2=p2->_next;
}
}
else
{
while(num--)
{
p2=p2->_next;
}
if(p1!=p2)
{
p1=p1->_next;
p2=p2->_next;
}
}
return p1;
}
3.判断两个链表是否相交,若相交,求交点。【升级版】 (假设链表可能带环)
第一步,找环中相汇点。分别用slow,fast指向链表头部,slow每次走一步,fast每次走二步,直到slow==fast找到在环中的相汇点。 第二步,找环的入口。接上步,当slow==fast时,fast所经过节点数为2x,slow所经过节点数为x,设环中有n个节点,fast比slow多走一圈有2x=n+x; n=x;可以看出slow实际走了一个环的步数,再让fast指向链表头部,slow位置不变,slow,fast每次走一步直到slow==fast; 此时slow指向环的入口。
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
ListNode* fast=pHead;
ListNode* slow=pHead;
while(fast!=NULL && fast->next!=NULL)
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow)
break;
}
if(fast==NULL || fast->next==NULL)
return NULL;
fast=pHead;
while(slow!=fast)
{
slow=slow->next;
fast=fast->next;
}
return fast;
}
4.复杂链表的复制。一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个random指针指向这个链表中的一个随机节点或者NULL,现在要求实现复制这个链表,返回复制后的新链表。
//ps: 复杂链表的结构struct ComplexNode
{
int _data ; // 数据
struct ComplexNode * _next; // 指向下一个节点的指针
struct ComplexNode * _random; // 指向随机节点(可以是链表中的任意节点 or 空)
};
第一步:复制所有链表的节点(设置next)
第二步:设置链表random指针。使用哈希表,将<N,N'>的对应关系
存到哈希表中,当设置时在O(1)时间就可以找到
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
if(pHead==NULL)
return NULL;
//定义一个哈希表
unordered_multimap<RandomListNode*,RandomListNode*> table;
// 开辟一个头结点
RandomListNode* pClonedHead=new RandomListNode(pHead->label);
pClonedHead->next=NULL;
pClonedHead->random=NULL;
// 将头结点放入map中
table.insert(make_pair(pHead,pClonedHead));
//设置操作指针
RandomListNode* pNode=pHead->next;
RandomListNode* pClonedNode=pClonedHead;
// 第一遍先将简单链表复制一下
while(pNode!=NULL)
{
// 不断开辟pNode的拷贝结点
RandomListNode* pClonedTail=new RandomListNode(pNode->label);
pClonedTail->next=NULL;
pClonedTail->random=NULL;
//连接新节点,更新当前节点
pClonedNode->next=pClonedTail;
pClonedNode=pCloneNode->next;//pNode比pClonedNode快了一个,所以要next之后再插入table
//将对应关系 插入到哈希表中
table.insert(make_pair(pNode,pClonedTail));//
//向后移动操作节点
pNode=pNode->next;
}
//需从头开始设置random节点,设置操作指针
pNode=pHead;
pClonedNode=pClonedHead;
// 根据map中保存的数据,找到对应的节点
while(pNode!=NULL)
{
if(pNode->random!=NULL)
{
//找到对应节点,更新复制链表
pClonedNode->random=table.find(pNode->random)->second;
}
//向后移动操作节点
pNode=pNode->next;
pClonedNode=pClonedNode->next;
}
return pClonedHead;
}
};