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;
}
相关推荐
aqymnkstkw1 小时前
2024年【电气试验】考试题库及电气试验模拟试题
大数据·c语言·人工智能·嵌入式硬件·安全
学习使我变快乐2 小时前
C++:用类实现链表,队列,栈
开发语言·c++·链表
重生之我要进大厂3 小时前
LeetCode 876
java·开发语言·数据结构·算法·leetcode
Happy鱿鱼3 小时前
C语言-数据结构 有向图拓扑排序TopologicalSort(邻接表存储)
c语言·开发语言·数据结构
KBDYD10103 小时前
C语言--结构体变量和数组的定义、初始化、赋值
c语言·开发语言·数据结构·算法
LWDlwd05253 小时前
shell指令及笔试题
c语言
Crossoads4 小时前
【数据结构】排序算法---桶排序
c语言·开发语言·数据结构·算法·排序算法
QXH2000004 小时前
数据结构—单链表
c语言·开发语言·数据结构
imaima6664 小时前
数据结构----栈和队列
开发语言·数据结构
David猪大卫4 小时前
数据结构修炼——顺序表和链表的区别与联系
c语言·数据结构·学习·算法·leetcode·链表·蓝桥杯