数据结构:随机链表的复制,对链表进行插入排序,删除排序链表中的重复元素 II

#define _CRT_SECURE_NO_WARNINGS 1

随机链表的复制

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,

该指针可以指向链表中的任何节点或空节点。

  • 在原链表中插入拷贝节点:将每个节点的拷贝插入到原链表中,这样可以在一次遍历中轻松找到每个节点和其拷贝节点的位置关系。
  • 设置拷贝节点的random指针 :利用拷贝节点插入原链表后的邻近关系,通过原节点的random指针,快速找到对应的拷贝节点的random
  • 拆解链表:恢复原链表,并同时提取出拷贝链表。

typedef struct Node Node;

struct Node {

int val;

struct Node* next;

struct Node* random;

};

struct Node* copyRandomList(struct Node* head) {

// 如果链表为空,直接返回NULL

if (head == NULL)

return NULL;

Node* cur = head;

// 1. 将原链表的每个节点复制一份,插入到原节点后面

while (cur) {

// 创建一个新的节点,值和原节点相同

Node* copy = (Node*)malloc(sizeof(Node));

copy->next = NULL;

copy->random = NULL;

copy->val = cur->val;

// 获取原节点的下一个节点

Node* next = cur->next;

// 将原节点的next指向新节点

cur->next = copy;

// 新节点的next指向原节点的下一个节点

copy->next = next;

// 移动到下一个原节点

cur = next;

}

// 2. 设置每个复制节点的random指针

cur = head;

while (cur) {

Node* copy = cur->next;

// 如果原节点有random指针,复制给新节点

if (cur->random) {

copy->random = cur->random->next; // 随机指针指向复制节点

}

else {

copy->random = NULL; // 如果没有随机指针,设置为NULL

}

// 迭代到下一个原节点

cur = cur->next->next;

}

// 3. 拆解链表,恢复原链表并分离出复制链表

cur = head;

Node* copyHead = head->next; // 复制链表的头节点

while (cur) {

Node* copy = cur->next; // 复制节点

Node* next = copy->next; // 复制节点的next

// 恢复原链表的结构:将原节点的next指向下一个原节点

cur->next = next;

// 将复制节点的next指向复制链表的下一个节点

if (next) {

copy->next = next->next; // 复制节点的next应该指向复制链表中的下一个节点

}

else {

copy->next = NULL; // 如果next为空,表示这是链表的最后一个复制节点

}

// 迭代到下一个原节点

cur = next;

}

// 返回复制链表的头节点

return copyHead;

}

对链表进行插入排序

给定单个链表的头 head ,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。

通过逐步扩展一个已排序部分的链表,将未排序部分的节点按照大小插入到适当位置,确保每一步都保持链表部分有序。

  • 初始状态:将链表的第一个节点视为已排序部分,后续节点逐一插入到该有序链表中。
  • 每步操作:找到当前节点在有序部分中的正确插入位置,并插入。
  • 完成条件:所有节点都被插入到有序链表中。

/**

* Definition for singly-linked list.

* struct ListNode {

* int val;

* struct ListNode *next;

* };

*/

typedef struct ListNode ListNode;

struct ListNode* insertionSortList(struct ListNode* head) {

if (head == NULL || head->next == NULL)

{

return head;

}

ListNode* sortHead = head;

ListNode* cur = head->next;

sortHead->next = NULL;

while (cur)

{

ListNode* next = cur->next;

//把cur插入到sortHead链表中去,并保持有序

if (cur->val <= sortHead->val)

{

//头插

cur->next = sortHead;

sortHead = cur;

}

else

{

//中间插

ListNode* sortPrev = sortHead;

ListNode* sortCur = sortPrev->next;

while (sortCur)

{

if (cur->val <= sortCur->val)

{

sortPrev->next = cur;

cur->next = sortCur;

break;

}

else

{

sortPrev = sortCur;

sortCur = sortCur->next;

}

}

//尾插

if (sortCur == NULL)

{

sortPrev->next = cur;

cur->next = NULL;

}

}

cur = next;

}

return sortHead;

}

删除排序链表中的重复元素 II

给定一个已排序的链表的头 head ,删除原始链表中所有重复数字的节点,

只留下不同的数字 。返回 已排序的链表 。

  • 遍历链表

    • 如果当前节点值和下一节点值相等,则跳过这些重复节点。
    • 如果当前节点值不等于下一节点值,则将其保留。
  • 处理重复节点

    • 通过内层循环跳过所有值相同的节点,找到第一个与当前值不同的节点。
    • 更新指针,删除重复的节点。
  • 特殊情况

    • 如果重复节点出现在链表开头,需要更新头指针。
    • 在链表尾部需要检查指针是否为 NULL,防止非法访问。

1.删除中间的情况

2.头相等

3.尾相等

/**

* Definition for singly-linked list.

* struct ListNode {

* int val;

* struct ListNode *next;

* };

*/

typedef struct ListNode ListNode;

struct ListNode* deleteDuplicates(struct ListNode* head) {

if(head==NULL || head->next==NULL)

return head;

ListNode* cur=head;

ListNode* next=cur->next;

ListNode* prev=NULL;

while(next)

{

if(cur->val!=next->val)//不相等继续往下走

{

prev=cur;

cur=next;

next=next->next;

}

else

{

while(next && cur->val == next->val) //对next进行解引用,必须保证next不为空才行

{

next=next->next;

}

//已经不相等了

if(prev)

{

prev->next=next;

}

else

{

head=next;

}

//释放

while(cur!=next)

{

ListNode* del=cur;

cur=cur->next;

free(del);

}

if(next)//尾相等的情况下需要判断,不为空才能继续赋值,否则会崩

{

next=cur->next;

}

}

}

return head;

}

相关推荐
余俊晖7 分钟前
Self-OPD:去掉教师机的流匹配模型 On-Policy 蒸馏
人工智能·算法·机器学习
手写码匠9 分钟前
华为云Flexus+DeepSeek征文|华为云MaaS DeepSeek推理服务 × Flexus云服务器 × Dify一键部署:性能评测实战
人工智能·深度学习·算法·aigc
啥都想学点的研究生1 小时前
一篇文章讲清楚:逻辑回归
算法·机器学习·逻辑回归
货拉拉技术2 小时前
Agent 场景下 Token 成本优化的实战技巧
算法
hahaha60162 小时前
HLS高层次综合设计技巧--循环merge和循环split
人工智能·算法·计算机视觉
JAI科研2 小时前
Deepseek Agent Harness教程(七) | Deepseek Harness不是一个内核加一堆插件
开发语言·人工智能·深度学习·算法·自然语言处理·transformer·vllm
positive_zpc2 小时前
进阶数据结构图——关键路径(四)
数据结构·图论·关键路径
集思广益的灰太狼2 小时前
变频器启动致PLC数据异常?西门子G120配合滤波器EMC抑制方案
人工智能·算法·工控·emc·电磁兼容·变频器·西门子
孙克旭_3 小时前
单链表进阶实操:5 道常考面试题详细解析【Java 实现】
java·开发语言·数据结构·单链表
方方洛3 小时前
vllm教程-03-架构设计
算法·架构