C语言数据结构:链表相关题目补充2

本篇文章涉及到前面文章的相关内容:

  1. C语言简单的数据结构:单链表的有关算法题(1)
  2. C语言简单的数据结构:单链表的有关算法题(2)
  3. C语言数据结构:链表相关题目补充1

本文内容如下:

1.环形链表1

这道题如果我们正常去用指针遍历的话,就会进入死循环

这时如果我们创建两个指针

一个指针一次走两步,另一个指针一次走一步

快指针先进入循环

当慢指针进入循环时,快指针开始追及慢指针

如果相遇就是带环链表

如果有一个走到NULL就是不带环

c 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode* head) {
    struct ListNode *fast = head, *slow = head;
    while (fast && fast->next) {
        fast = fast->next->next;
        slow = slow->next;
        if (slow == fast) {
            return true;
        }
    }
    return false;
}

理解完思路代码就比较简单了

2.环形链表2

这次问的就点意思了,一共有两种解法:

解法一:数学思维

我们先标明长度关系:

C ------------环的长度

L ------------进入环前长度

N ------------环内相遇到进环的长度

我们通过数学关系就能的到:

此时刚好进环前的距离和相遇后到进环的距离长度是一样的

那么这样创建两个指针,当他俩刚好相遇时就是进环的点

c 复制代码
struct ListNode* detectCycle(struct ListNode* head) {
    struct ListNode *fast = head, *slow = head, *meet;
    while (fast && fast->next) {
        fast = fast->next->next;
        slow = slow->next;
        if (slow == fast) {
            meet = fast;
            slow = head;
            while (slow != meet) {
                slow = slow->next;
                meet = meet->next;
            }
            return meet;
        }
    }
    return false;
}

解法二:改为链表相交问题

我们可以在相交的位置将带环链表解开

然后转换为链表相交问题

链表相交问题的解法: C语言数据结构:链表相关题目补充1

c 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* getIntersectionNode(struct ListNode* headA,
                                     struct ListNode* headB) {
    struct ListNode* cur1 = headA;
    struct ListNode* cur2 = headB;
    int len1 = 1, len2 = 1;
    while (cur1->next) {
        cur1 = cur1->next;
        ++len1;
    }
    while (cur2->next) {
        cur2 = cur2->next;
        ++len2;
    }
    if (cur1 != cur2) {
        return NULL;
    }
    int a = abs(len1 - len2);
    struct ListNode *longList = headA, *shortList = headB;
    if (len2 > len1) {
        shortList = headA;
        longList = headB;
    }
    while (a--) {
        longList = longList->next;
    }
    while (longList != shortList) {
        longList = longList->next;
        shortList = shortList->next;
    }
    return longList;
}

struct ListNode* detectCycle(struct ListNode* head) 
{
    struct ListNode *fast = head, *slow = head, *meet;
    while (fast && fast->next) 
    {
        fast = fast->next->next;
        slow = slow->next;
        if (slow == fast) 
        {
            meet = fast;
            struct ListNode* newhead = meet->next;
            meet->next = NULL;
            return getIntersectionNode(head,newhead);
        }
    }
    return false;
}

我们将其拆开,然后就是相交链表的计算了

2.随机链表的复制

给定一个链表,每个结点包含一个额外增加的随机指针,该指针可以指向链表中的任何结点或空结点。

要求返回这个链表的深度拷贝。

这道题目前只有一个比较好的解法:

  1. 先将链表正常拷贝下来,无random节点
  2. 将其尾插在原链表后面
  3. 实现random的链接
  4. 将链表拆下来

1.拷贝原链表

c 复制代码
struct Node* copyRandomList(struct Node* head) {
	struct Node* cur = head;
    while(cur)
    {
        struct Node* copy =(struct Node*)malloc(sizeof(struct Node));
        copy->val = cur->val;
        copy->next = cur->next;
    }
}

2.将拷贝链表各个节点尾插到原链表中

c 复制代码
struct Node* copyRandomList(struct Node* head) {
    struct Node* cur = head;
    while (cur) {
        struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
        copy->val = cur->val;
        copy->next = cur->next;

        cur->next = copy;
        cur = copy->next
    }
}

3.让创建的链表random节点指向正确的位置

这里恰好复制的节点就是 原链表的random指向的节点的next

c 复制代码
 while (cur) 
    {
        struct Node* copy = cur->next;
        if (cur->random == NULL) 
        {
            copy->random = NULL;
        }
        else 
        {
            copy->random = cur->random->next;
        }
        cur = copy->next;
    }

4.最后将节点链表拆下来就行了

c 复制代码
struct Node*copyhead = NULL,*copytail=NULL;
    cur=head;
    while(cur)
    {
        struct Node *copy =cur->next;
        struct Node* next = copy->next;

        if(copytail == NULL)
        {
            copyhead = copytail =copy;
        }
        else{
            copytail->next = copy;
            copytail =copytail->next;
        }
        cur = next;
    }

最后汇总到一起就行了:

c 复制代码
/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */

struct Node* copyRandomList(struct Node* head) {
    struct Node* cur = head;
    while (cur) {
        struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
        copy->val = cur->val;
        copy->next = cur->next;

        cur->next = copy;
        cur = copy->next;
    }
    cur = head;

    while (cur) 
    {
        struct Node* copy = cur->next;
        if (cur->random == NULL) 
        {
            copy->random = NULL;
        }
        else 
        {
            copy->random = cur->random->next;
        }
        cur = copy->next;
    }
    
    struct Node*copyhead = NULL,*copytail=NULL;
    cur=head;
    while(cur)
    {
        struct Node *copy =cur->next;
        struct Node* next = copy->next;

        if(copytail == NULL)
        {
            copyhead = copytail =copy;
        }
        else{
            copytail->next = copy;
            copytail =copytail->next;
        }
        cur = next;
    }
    return copyhead;
}
相关推荐
青岛少儿编程-王老师3 小时前
CCF编程能力等级认证GESP—C++7级—20250927
数据结构·c++·算法
小莞尔5 小时前
【51单片机】【protues仿真】基于51单片机全自动洗衣机系统
c语言·单片机·嵌入式硬件·物联网·51单片机
nanaki502135 小时前
数据结构(3) ----------- 栈、队列
数据结构
一只小透明啊啊啊啊5 小时前
b树,b+树,红黑树
数据结构·b树·b+树
Mingze03146 小时前
C语言四大排序算法实战
c语言·数据结构·学习·算法·排序算法
程序员东岸6 小时前
学完顺序表后,用 C 语言写了一个通讯录
数据结构·笔记·学习
小龙报6 小时前
《彻底理解C语言指针全攻略(3)》
c语言·开发语言·windows·git·创业创新·学习方法·visual studio
独自破碎E7 小时前
Leetcode2166-设计位集
java·数据结构·算法
Cikiss7 小时前
LeetCode160.相交链表【最通俗易懂版双指针】
java·数据结构·算法·链表
很㗊7 小时前
C与C++---指针、引用、结构体及内存管理
c语言·开发语言