当前位置: 首页 > news >正文

【初阶数据结构】顺序表和链表算法题(下)

链表

  • 2.链表
    • 2.4合并两个有序链表
    • 2.5链表分割
    • 2.6链表的回⽂结构
    • 2.7相交链表
    • 2.8环形链表I
    • 2.9 环形链表II
    • 2.10随机链表的复制

2.链表

2.4合并两个有序链表

在这里插入图片描述
思路
在这里插入图片描述

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
typedef struct ListNode ListNode;
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {//处理链表为空的情况if (list1 == NULL)return list2;if (list2 == NULL)return list1;//方一代码:创建新的空链表ListNode* newhead = NULL, * newtail = NULL;//list1,list2分别指向两个链表的表头//newhead = newtail = (ListNode*)malloc(sizeof(ListNode));while (list1 && list2)//只要有一个条件不满足就跳出循环{if (list1->val < list2->val){//谁小谁尾插if (newhead == NULL){newhead = newtail = list1;}else{newtail->next = list1;newhead = newtail->next;}list1 = list1->next;}else{//l2尾插if (newhead == NULL){newhead = newhead = list2;}else{newtail->next = list2;newtail = newtail->next;}list2 = list2->next;}}//跳出循环只有两种情况,list1为空或list2为空if (list1){newtail->next = list1;}if (list2){newtail->next = list2;}return newhead;
}
//方二代码:创建一个非空链表
typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {//申请一个动态的空间//此时初始了一个头结点,是个默认的值,最后删掉ListNode* newhead, * newtail;newhead = newtail = (ListNode*)malloc(sizeof(ListNode));while (list1 && list2){//不用判断链表是否为空,直接拿过来尾插if (list1->val < list2->val){newtail->next = list1;list1 = list1->next;}else{newtail->next = list2;list2 = list2->next;}newtail = newtail->next;}if (list1){newtail->next = list1;}else{newtail->next = list2;}ListNode* ret = newhead->next;free(newhead);newhead = NUll;return ret;
}

2.5链表分割

在这里插入图片描述
思路
在这里插入图片描述

单链表算法题----链表分割
牛客是c++写的
/*
struct ListNode {int val;struct ListNode *next;ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:ListNode* partition(ListNode* pHead, int x) {// write code hereif (pHead == NULL)return NULL;//创建两个非空链表,小链表和大struct ListNode* lessHead, * lessTail, * greaterHead, * greaterTail;//创建链表表头//注意:我动态开辟空间后 lesshead链表和greathead链表头就有一个默认结点啦lessHead = lessTail = (struct ListNode*)malloc(sizeof(struct ListNode));greaterHead = greaterTail = (struct ListNode*)malloc(sizeof(struct ListNode));//遍历原链表,找小于x的和其它节点尾插导大小链表中struct ListNode* cur = pHead;while (cur){//小于x的尾插到lessTailif (cur->val < x){lessTail->next = cur;lessTail = lessTail->next;}//大于等于x的尾插到greaterTailelse{greaterTail->next = cur;greaterTail = greaterTail->next;}cur = cur->next;}//链接两个链表,小尾结点指向大的下一个结点lessTail->next = greaterHead->next;greaterTail->next = NULL;//获取表头pHead = lessHead->next;free(lessHead);free(greaterHead);return pHead;}
};

2.6链表的回⽂结构

在这里插入图片描述
思路
在这里插入图片描述

单链表算法题----链表的回⽂结构
/*
struct ListNode {int val;struct ListNode *next;ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:bool chkPalindrome(ListNode* A) {// write code hereif (A == NULL || A->next == NULL)return true;ListNode* slow, * fast, * prev, * cur, * nxt;slow = fast = A;//1.找到中间节点while (fast && fast->next){slow = slow->next;fast = fast->next->next;}//此时slow为中间结点 //后半部分逆置(反转链表)prev = NULL;cur = slow;while (cur){nxt = cur->next;cur->next = prev;prev = cur;cur = nxt;}//逐点比对while (A && prev)//此时prev为最后一个结点{if (A->val != prev->val)return false;A = A->next;prev = prev->next;}return true;}
};

2.7相交链表

在这里插入图片描述
思路

在这里插入图片描述

单链表算法题----相交链表
/*** 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* p1 = headA;ListNode* p2 = headB;int sizeA, sizeB;sizeA = sizeB = 0;while (p1) {sizeA++;p1 = p1->next;}while (p2) {sizeB++;p2 = p2->next;}//求绝对值int gap = abs(sizeA - sizeB);//让长链表先走gap步ListNode* longlist = headA;ListNode* shortlist = headB;if (sizeA < sizeB){longlist = headB;shortlist = headA;}while (gap--){longlist = longlist->next;}//此时,longlist和shortlist在同一起跑线//两种情况  相交,不相交while (longlist && shortlist){if (longlist == shortlist){//链表相交return shortlist;}//继续往后走longlist = longlist->next;shortlist = shortlist->next;}//都走到为空了,链表不相交return NULL;
}

在这里插入图片描述

2.8环形链表I

在这里插入图片描述
思路证明见下篇
在这里插入图片描述
在这里插入图片描述

单链表算法题----环形链表I
//判断是否带环
//判断是否相遇,环形链表2下个题是找相遇点
/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
//走两步
typedef struct ListNode ListNode;
bool hasCycle(struct ListNode* head) {//快慢指针ListNode* slow, * fast;slow = fast = head;while (fast && fast->next){slow = slow->next;fast = fast->next->next;if (slow == fast){return true;}}//两个指针始终没有相遇return false;
}
//走三步
typedef struct ListNode ListNode;
bool hasCycle(struct ListNode* head) {//快慢指针ListNode* slow, * fast;slow = fast = head;while (fast && fast->next){slow = slow->next;int n = 3;//fast每次⾛三步while (n--)//进去3次{if (fast->next)fast = fast->next;else//不带环return false;}if (slow == fast){return true;}}//两个指针没有相遇return false;
}

2.9 环形链表II

在这里插入图片描述
结论
让⼀个指针(pcur)从链表起始位置开始遍历链表,同时让⼀个指针(next)从判环时相遇点(meet)的位置开始绕环运⾏,两个指针都是每次均走⼀步,最终肯定会在入口点的位置相遇。

第一步,找环的相遇点
第二步,从头结点和相遇点开始遍历,每次都走一步
第三步,当pcur和meet相遇时,即入口点

单链表算法题----环形链表II
//先运用找相遇点代码
/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
typedef struct ListNode ListNode;
ListNode* FindNode(ListNode* head)
{ListNode* fast, * slow;slow = fast = head;while (fast && fast->next){slow = slow->next;fast = fast->next->next;if (slow == fast)return slow;//相遇了}return NULL;
}
struct ListNode* detectCycle(struct ListNode* head) {//找环的相遇点ListNode* meet = FindNode(head);//从头结点和相遇点开始遍历,每次都走一步ListNode* pcur = head;while (meet && pcur){//当pcur和meet相遇时,即入口点if (meet == pcur)return meet;meet = meet->next;pcur = pcur->next;}//链表不带环return NULL;
}

2.10随机链表的复制

在这里插入图片描述
在这里插入图片描述
思路

第一步,在原链表基础上继续复制链表
第二步,置random指针,copy->random=pcur->random->next
第三步,复制链表与原链表断开
在这里插入图片描述
`

`附上几张图便于理解

在这里插入图片描述
第三步的时候 下图
在这里插入图片描述

单链表算法题----随机链表的复制
/*** Definition for a Node.* struct Node {*     int val;*     struct Node *next;*     struct Node *random;* };*/typedef struct Node Node;
Node* BuyNode(int x)
{Node* newnode = (Node*)malloc(sizeof(Node));newnode->val = x;newnode->next = newnode->random = NULL;return newnode;
}
//原链表传过来,复制链表
void AddNode(Node* phead)
{Node* pcur = phead;while (pcur){Node* ret = pcur->next;//创建新节点,尾插到pcur Node* newnode = BuyNode(pcur->val);pcur->next = newnode;newnode->next = ret;pcur = ret;}
}
struct Node* copyRandomList(struct Node* head) {if (head == NULL)return NULL;//第一步AddNode(head);//第二步Node* copy, * pcur, * p1, * newhead, * newtail;pcur = head;newhead = newtail = pcur->next;p1 = pcur;while (pcur){copy = pcur->next;if (pcur->random != NULL){//如果为空,copy->random本来就是null,不用再改了copy->random = pcur->random->next;}pcur = copy->next;}//第三步//让pcur再回到头结点,所以有了p1while (p1->next->next){p1 = p1->next->next;newtail->next = p1->next;newtail = newtail->next;}return newhead;
}
``更多链表算法刷题⼊⼝:
⽜客⽹:https://www.nowcoder.com/exam/oj
LeetCode:https://leetcode.cn/problems/copy-list-with-random-pointer/description/

http://www.mrgr.cn/news/13782.html

相关文章:

  • ADB 获取屏幕坐标,并模拟滑动和点击屏幕
  • C++ 两线交点程序(Program for Point of Intersection of Two Lines)
  • 数据仓库系列 2:数据仓库的核心特点是什么?
  • 解决Selenium已安装,在pycharm导入时报错
  • 如何将十六进制的乱码转换成汉字
  • Java 输入与输出之 NIO【非阻塞式IO】【NIO核心原理】探索之【一】
  • 数据链路层(Mac帧,报头字段,局域网通信原理),MTU,MSS,ip报文的分包与组装(ip报头字段介绍,组装过程,判断是否被分片/收到全部分片)
  • 手机游玩植物大战僵尸杂交版V2.3.7最新版教程(文章末尾免费直接下载链接)
  • 跨境电商避坑指南:如何在亚马逊和速卖通安全进行测评补单
  • Linux—信号量
  • sql实现按照自定义顺序 排序
  • vue3实现excel文件预览和打印
  • 利用移动语义优化 C++ 程序性能的实用指南
  • easyExcel 单元格合并
  • Image Stride(内存图像行跨度)
  • 初识Vue.js:从零开始构建你的第一个Vue项目
  • 在Linux中杀死占用某个端口的进程
  • pymysql cursor使用教程
  • DARKTIMES集成到Sui,带来中世纪格斗大逃杀游戏体验
  • Java使用Tesseract进行OCR图片文字识别