算法(相交链表和随机链表复制)

༺ 个人主页 · 纪念229 ༻

🏠我的博客主页🏠

༒专栏目录:《数据结构》༒

༒其它有趣的计算机知识༒

༺世上本没有路,走的人多了自然就有了༻


本文讲述的是本人在LeetCode见到的两个算法题,个人见解感谢观看。

此外还给出题目的网址

相交链表

随机链表的复制

本文的相交链表是以单链表构成的,而随机链表和单链表差不多但结构里多了个随即指向某节点的指针

文章目录

1.相交链表

我们来看一下题目

讲述的是两个单链表从头节点出发要求我们找到相同地址的节点并返回,如果没有就返回NULL

注链表不成环且不能破坏链表结构

代码实现

c 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

 typedef struct ListNode ListNode;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
   ListNode* LA = headA;
   ListNode* LB = headB;
   while(LA != LB)
   {
     LA = LA == NULL ? headB : LA->next;   
     LB = LB == NULL ? headA : LB->next;   
   }
   return LA;
}

注意LeetCode题大多数只要求写核心代码即可完成OJ

代码讲解:代码开头那个被注释的代码我们可以看到链表结构是由单链表构成的

核心逻辑:用了一个判断语句,指针LA从headA出发遍历链表A,走到末尾NULL时就切换到headB继续遍历;指针LB从headB出发遍历链表B,走到末尾NULL时切换到headA继续遍历。二者走过的总路程完全相等,若两链表存在相交节点,两个指针必然会在交点处相遇,循环终止后返回相遇节点;若两链表完全无交点,最终二者会同时走到NULL并相等,最后返回NULL。

2.随机链表的复制

题目如下

实现随机连表的复制只需要实现以下几个步骤:

1.考虑原链表是否为空链表

2.在每个原节点中插入拷贝节点

3.设置拷贝节点中的random指针

4.双指针拆分链表

代码实现

c 复制代码
/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */
typedef struct Node Node;
struct Node* copyRandomList(struct Node* head) {
    //考虑原节点是否为空节点
    if(head == NULL)
    return NULL;
	//在每个原节点后插入拷贝节点
    //用cur指针遍历
    Node* cur = head;
    while(cur)
    {
        Node* copy = (Node*)malloc(sizeof(Node));
        copy->val = cur->val;
        copy->next = cur->next;
        cur->next = copy;
        cur = copy->next;
    }
    //设置拷贝节点random指针
    //cur复位
    cur = head;
    while(cur)
    {
        Node* copy = cur->next;
        //判断cur的随机节点是否为空 , 不为copy的随机节点为cur的随机节点的下一位也就是拷贝节点的随机节点 ,为NULL拷贝节点的随机节点结尾NULL
        copy->random = ( cur->random != NULL) ? cur->random->next : NULL;
        cur = copy->next;
    }
    //双指针拆开两链表
    //cur复位
    //弄个拷贝节点的头,遍历拷贝指针
    cur = head;
    Node* copyHead = cur->next;
    Node* copyCur = copyHead;
    while(cur != NULL)
    {
        cur->next = copyCur->next;
        cur = cur->next;
        //各自连自己的,如果cur为NULL结束 ,拷贝节点不能接着连
        //最后新旧节点尾都会连接NULL
        if(cur != NULL)
        {
        copyCur->next = cur->next;
        copyCur = copyCur->next;
        }
    }
     return copyHead;
}

2.1考虑原链表是否为空链表

当原链表为空链表时随机链表复制的就是NULL,返回NULL即可

2.2 在每个原节点后插入拷贝节点

给一个cur指针遍历,每次循环都创建一个节点copy然后复制cur里面的val和next,用cur连接copy(注意此时我们的copy连接的是原cur的下一个节点)然后用cur 赋值为copy下一个节点遍历即可

2.3设置拷贝节点random指针

首先我们要给cur复位(回到原链表的头节点)

判断cur的随机节点是否为空 , 不为copy的随机节点为cur的随机节点的下一位也就是拷贝节点的随机节点 ,为NULL拷贝节点的随机节点结尾NULL

这里就有点绕我们知道copy在cur的后面是个拷贝节点

当cur等于A时copy等于拷贝的A假如A random后是 C 那么 拷贝的A random 就是 拷贝的C

2.4双指针拆开两链表

首先给cur复位

然后用双指针遍历用原节点连接原节点,如果循环里面的cur不为空就用拷贝节点连接拷贝节点

各自连自己的,如果cur为NULL结束 ,说明拷贝节点已经连完

最后新旧节点尾都会连接NULL


文章到这里就告一段落,看到这里希望对你有所帮助,感谢观看!