给一个长度为n链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null。
数据范围:
,
要求:空间复杂度
,时间复杂度
例如,输入{1,2},{3,4,5}时,对应的环形链表如下图所示:
可以看到环的入口结点的结点值为3,所以返回结点值为3的结点。
输入分为2段,第一段是入环前的链表部分,第二段是链表环的部分,后台会根据第二段是否为空将这两段组装成一个无环或者有环单链表
返回链表的环的入口结点即可,我们后台程序会打印这个结点对应的结点值;若没有,则返回对应编程语言的空结点即可。
{1,2},{3,4,5}3
返回环形链表入口结点,我们后台程序会打印该环形链表入口结点对应的结点值,即3
{1},{}"null"
没有环,返回对应编程语言的空结点,后台程序会打印"null"
{},{2}
2
环的部分只有一个结点,所以返回该环形链表入口结点,后台程序打印该结点对应的结点值,即2
typedef struct ListNode ListNode;
ListNode* EntryNodeOfLoop(ListNode *head)
{
//没有结点,则无所谓环,更无所谓pos
if(!head)
{
return NULL;
}
ListNode* slow = head;
ListNode* fast = head;
ListNode* meet = head;
while(fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
//有环,进入找pos环节
if(fast == slow)
{
while(meet != slow)
{
meet = meet->next;
slow = slow->next;
}
return meet;
}
}
//走到这里,说明没环
return NULL;
} struct ListNode* EntryNodeOfLoop(struct ListNode* pHead ) {
struct ListNode *buffer[10000], *p1=pHead;
int bufferLen=0;
if(pHead==NULL)
return NULL;
while(p1->next!=NULL) {
int i;
for(i=0;i<bufferLen;i++) {
if(p1==buffer[i])
return buffer[i];
}
buffer[i] = p1;
bufferLen++;
p1 = p1->next;
}
return NULL;
} /**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param pHead ListNode类
* @return ListNode类
*/
#include <stdio.h>
bool find(struct ListNode* pHead ){
struct ListNode* fast=pHead;
struct ListNode* slow=pHead;
while(fast!=NULL && slow!=NULL){
if(fast->next!=NULL){
fast=fast->next->next;
}else{
return false;
}
slow=slow->next;
if(slow==fast){
return true;
}
}
return false;
}
struct ListNode* cai(int v){
struct ListNode* round=(struct ListNode*)malloc(sizeof(struct ListNode));
round->val=v;
round->next=NULL;
return round;
}
struct ListNode* EntryNodeOfLoop(struct ListNode* pHead ) {
// write code here
struct ListNode* node=pHead;
struct ListNode* round=(struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode* kk=(struct ListNode*)malloc(sizeof(struct ListNode));
kk=round;
int i=0;
struct ListNode* nullnode=NULL;
if(!find(pHead)){
return nullnode;
}else{
while(1){
struct ListNode* ff=kk->next;
while(ff!=NULL){
if(ff->val==node->val){
return ff;
}
ff=ff->next;
}
round->next=cai(node->val);
round=round->next;
node=node->next;
}
}
} struct ListNode* EntryNodeOfLoop(struct ListNode* pHead ) {
// write code here
struct ListNode* p = pHead;
struct ListNode* q = pHead;
while (p->next != NULL)
{
q = pHead;
p = p->next;
while (true)
{
if(q == p->next)
{
return q;
}
if(q == p)
{
break;
}
q = q->next;
}
}
return NULL;
} struct ListNode* EntryNodeOfLoop(struct ListNode* pHead ) {
struct ListNode*p1=pHead,*p2=pHead,*r=pHead;
while(p1&&p2){
p1=p1->next;
p2=p2->next;
if(p2) p2=p2->next;
if(p1==p2&&p1){
while(p1!=r){
r=r->next;
p1=p1->next;
}
return r;
}
}
return NULL;
}
//这个不是一般的好理解,不用一步两步
struct ListNode* EntryNodeOfLoop(struct ListNode* pHead ) {
// write code here
int i=0;
struct ListNode*pre=pHead;
struct ListNode*temp=pHead;
while(pre!=NULL){
pre=pre->next;
i++;
if(i>10000) break;
}
if(i<10000) return NULL;
while(temp->val>0){
temp->val=temp->val-10000;
temp=temp->next;
}
struct ListNode*head=temp;
while(temp->val<1){
temp->val=temp->val+10000;
temp=temp->next;
}
return head;
} /**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param pHead ListNode类
* @return ListNode类
*/
struct ListNode* EntryNodeOfLoop(struct ListNode* pHead ) {
// write code here
//空链表和单个节点链表直接返回
if(!pHead || !pHead->next)
return NULL;
/*
因为节点值[1, 10000]
因此,依次遍历节点,将节点值取反(*-1),
如果遇到next节点值<0,则该节点为环的入口,
将该节点值再次取反,并返回该节点即可。
*/
while(pHead)
{
if(pHead->val < 0)
{
pHead->val *= (-1);
return pHead;
}
pHead->val *= (-1);
pHead = pHead->next;
}
return NULL;
} struct ListNode* EntryNodeOfLoop(struct ListNode* pHead ) {
struct ListNode*fast=pHead;
struct ListNode*slow=pHead;
while(fast&&fast->next){
fast=fast->next->next;
slow=slow->next;
if(fast==slow){
struct ListNode* tmp=pHead;
while(tmp!=slow){
tmp=tmp->next;
slow=slow->next;
}
return tmp;
}
}
return NULL;
}
当第二个指针指向环的入口结点时,第一个指针已经围绕着环走了一圈又回到了入口结点。
public class 链表中环的入口结点 { //找到一快一满指针相遇处的节点,相遇的节点一定是在环中 public static ListNode meetingNode(ListNode head) { if(head==null) return null; ListNode slow = head.next; if(slow==null) return null; ListNode fast = slow.next; while (slow != null && fast != null) { if(slow==fast){ return fast; } slow=slow.next; fast=fast.next; if(fast!=slow){ fast=fast.next; } } return null; } public ListNode EntryNodeOfLoop(ListNode pHead) { ListNode meetingNode=meetingNode(pHead); if(meetingNode==null) return null; // 得到环中的节点个数 int nodesInLoop=1; ListNode p1=meetingNode; while(p1.next!=meetingNode){ p1=p1.next; ++nodesInLoop; } // 移动p1 p1=pHead; for(int i=0;i<nodesInLoop;i++){ p1=p1.next; } // 移动p1,p2 ListNode p2=pHead; while(p1!=p2){ p1=p1.next; p2=p2.next; } return p1; } }