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;
}
相关推荐
小刘在重生~20 分钟前
Java 集合|Collection、List、ArrayList、LinkedList、泛型、Collections 工具类
java·数据结构·list
我不会起名字32235 分钟前
一天一道算法题(29):单调栈
java·数据结构·python·算法·leetcode·golang·单调栈
SuperByteMaster39 分钟前
编译器将unsigned short 整体提升int和unsigned short 在内存中的分配2byte的理解
c语言
苦瓜小生1 小时前
【前端】【力扣与手撕】十天带你刷完前端算法与手撕,全是最简单好记的最优解法!day4
前端·数据结构·算法·leetcode·面试
XiaoQiao6669991 小时前
C 语言常用头文件及里面核心函数
c语言·开发语言
少司府2 小时前
C++进阶:智能指针
开发语言·数据结构·c++·b树·算法·c·智能指针
博界IT精灵2 小时前
C语言中的数据类型及其转换
c语言·开发语言
水饺编程3 小时前
编程数学:三角函数基础01,直角三角函数
c语言·c++·windows·visual studio
LuminousCPP3 小时前
数据结构-排序(一):基础排序算法横向对比|冒泡、插入、希尔、堆与双向选择,详解二分 / Knuth 增量
c语言·数据结构·笔记·算法·排序算法
初願致夕霞3 小时前
C/C++传统程序内存分布(代码实测)
java·c语言·c++