【数据结构篇】~链表算法题3(环形链表)


请添加图片描述

环形链表的证明

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

1. 环形链表I​

在这里插入图片描述

https://leetcode.cn/problems/linked-list-cycle/description/

1) 思路

在这里插入图片描述

判断链表是否带环,还是要使用快慢双指针,如果带环那他们一定在环中相遇,如果没带环那么就返回false

2)代码实现

typedef struct ListNode ls;
bool hasCycle(struct ListNode *head) {
    ls*slow=head,*fast=head;
    //开始循环
    while(fast && fast->next)//分为奇数偶数两种情况所以要fast&&fast->next
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
        return true;
    }
    return false;   
}

2. 环形链表II​

https://leetcode.cn/problems/linked-list-cycle-ii/description/​

在这里插入图片描述
在这里插入图片描述

1) 思路1

找到相遇节点,然后把相遇节点的next指针置为newnode,再把meet->next置为空,这时再找入环节点就可以转化为找相交链表的相交节点

1) 思路2

找到相遇节点后然后开时循环,让相遇节点和头节点同时同步走,直到两个指针相遇时,就找到了入环节点

2)代码实现

typedef struct ListNode lsnode;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
    lsnode*l1=headA;
    lsnode*l2=headB;
    int sizea=0;int sizeb=0;
    while(l1)
    {
       ++sizea;
        l1=l1->next;      
    }
    while(l2)
    {
        ++sizeb;
        l2=l2->next;     
    }
    //计算a和b的长度,让长的先走差值步,到同一起点上
     lsnode* plong = headA;
    lsnode* pshort = headB;
    if(sizeb>sizea)
    {
        plong= headB;
        pshort=headA;
    }
    

    int gap=abs(sizea-sizeb);
    while(gap--)
    {
        plong = plong -> next;
    }
    //开始比较
    while(plong && pshort)
    {
        //这里比较地址,如果比较值得话有问题
        if(plong == pshort)
       { 
        return pshort;
       }
       //同步走
        plong=plong->next;
        pshort=pshort->next;    
    }
    return NULL;   
}
struct ListNode *detectCycle(struct ListNode *head) 
{
    lsnode*slow=head,*fast=head;
    while(fast && fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
        {
            lsnode*meet=slow;//相遇节点
            lsnode*newhead=meet->next;
            meet->next=NULL;//变为了相交链表找相交节点
            return getIntersectionNode(head,newhead);
        }       
    }  
     return NULL;
}

```c
typedef struct ListNode  lsnode;
struct ListNode *detectCycle(struct ListNode *head) 
{
     lsnode*slow=head,*fast=head;
    while(fast && fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
        {
            lsnode*meet=slow;//相遇节点
            while(head!=meet)
            {
                head=head->next;
                meet=meet->next;
            }
            return meet;
        }      
    }  
     return NULL;   
}

3. 随机链表的复制​

https://leetcode.cn/problems/copy-list-with-random-pointer/description/​
在这里插入图片描述

1) 思路

深拷贝就是把所有数据都复制下来,创建节点malloc,放置当前节点的next,当前节点再往后走2个next,然后再创建复制节点

在这里插入图片描述

2)代码实现

typedef struct Node node;
node* buynode(int val)//申请新节点
{
	node* newnode = (node*)malloc(sizeof(node));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(1);
	}
	newnode->val = val;
	newnode->next = newnode->random = NULL;
	return newnode;
}
struct Node* copyRandomList(struct Node* head)
{
    if(head==NULL) return NULL; 
	node* phead1 = head;//复制节点用
	node* phead2 = head;//尾插用
    node* phead3 = head;//置random用
	while (phead1)//开始复制节点
	{
		node* newnode = buynode(phead1->val);
		newnode->next = phead1->next;
		phead1->next = newnode;
		phead1 = newnode->next;
	}
    //置random要和复制链表分开
    
    while(phead3)
    {
        node* newnode1=phead3->next;
        if(phead3->random != NULL)
		{
			newnode1->random = phead3->random->next;
		}
        phead3=newnode1->next;
    }
	//这里是尾插
	node* newhead,* newtail;
	newhead = newtail = phead2->next;//第一个复制的节点
		while (phead2->next->next)
		{
			phead2 = phead2->next->next;
			newtail->next = phead2->next;
			newtail = newtail->next;			
		}
		return newhead;	
}
``
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值