算法训练 —— 链表(2)

news/2024/11/17 10:24:11/

目录

1. LeetCode24. 两两交换链表中的结点

2. LeetCode19. 删除链表的倒数第N个节点

3. LeetCode160.相交链表

4. LeetCode141.环形链表

5. LeetCode142.环形链表II

6. LeetCode138.复制带随机指针的链表 


1. LeetCode24. 两两交换链表中的结点

两两交换链表中的结点 

/*解法1:迭代。。设置虚拟头结点*/
class Solution {
public:ListNode* swapPairs(ListNode* head) {ListNode* res = new ListNode(-1);// 设置一个虚拟头结点res->next = head;// 将虚拟头结点指向head,这样方面后面做删除操作ListNode* cur = res;while(cur->next != nullptr && cur->next->next != nullptr){ListNode* tmp = cur->next;// 记录临时节点ListNode* tmp1 = cur->next->next->next;cur->next = cur->next->next;  // 步骤一cur->next->next = tmp;        // 步骤二cur->next->next->next = tmp1; // 步骤三cur = cur->next->next;// cur移动两位,准备下一轮交换}return res->next;}
};

 

 

/*解法2:递归*/
class Solution {
public:ListNode* swapPairs(ListNode* head) {//如果链表结点个数为0或1,这时候直接返回head,不需要交换if(head == nullptr || head->next == nullptr) return head;ListNode* prev = head;ListNode* cur = prev->next;ListNode* next = cur->next;//交换两个节点prev->next = next;cur->next = prev;//以 1->2->3->4->5->nullptr 为例//交换之后为 2->1->3->4->5->nullptr//因为head是指向1的,所有递归调用的结果返回给head->nexthead->next = swapPairs(next);return cur;}
};

解法2图解: 

 

//解法3:
class Solution {
public:ListNode* swapPairs(ListNode* head) {if(head == nullptr || head->next == nullptr) return head;ListNode* newhead = head->next;ListNode* tmp = nullptr;ListNode* prev = head;ListNode* cur = prev->next;ListNode* next = cur->next;while(prev != nullptr && prev->next != nullptr){cur->next = prev;prev->next = next;if(tmp != nullptr) tmp->next = cur;tmp = prev;prev = next;if(prev != nullptr)cur = prev->next;if(cur != nullptr) next = cur->next;}return newhead;}
};

        解法3:是不用虚拟的头结点,直接在原链表交换,是一种不错的思路,但是理解起来不是那么容易,建议上面两种方法的理解,下面是图解过程

 

 

2. LeetCode19. 删除链表的倒数第N个节点

删除链表的倒数第N个节点 

class Solution {
public:ListNode* removeNthFromEnd(ListNode* head, int n) {//给链表设置一个虚拟头结点(哨兵结点),有效防止删除正数第一个的情况,避免更新头结点ListNode* res = new ListNode(-1);res->next = head;ListNode* fast = head;ListNode* slow = head;ListNode* prev = res;while(n--)//因为题目中n是有效的,所以我们让快指针先走n步{fast = fast->next;}while(fast)//然后fast和slow一起走{fast = fast->next;prev = slow;//一起走之前,先记录一下slow的位置,当fast走到空时,slow一定走到了倒数第n个节点上slow = slow->next;}prev->next = slow->next;return res->next;}
};

 

3. LeetCode160.相交链表

相交链表 

 

//解法1:
class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode* pA = headA;ListNode* pB = headB;//你可以算一算图中的pA走完headA从headB开始走到交点,和pB走完headB从headA开始走到交点距离是一样的while(pA != pB)//pA == pB时退出,表明走到了交点{// pA 将headA链表走完了,就去走headB链表pA = pA == nullptr ? headB : pA->next;// pB 将headB链表走完了,就去走headA链表pB = pB == nullptr ? headA: pB->next;}return pA;}
};//解法2;
class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode* tailA = headA;ListNode* tailB = headB;int lenA = 1;while(tailA->next)//计算链表A的长度{++lenA;tailA = tailA->next;}int lenB = 1;while(tailB->next)//计算链表B的长度{++lenB;tailB = tailB->next;}if(tailA != tailB)//两个链表都走完了,但是不相等,表明一定没有交点{return nullptr;}int gap = abs(lenB - lenA);//算出长短链表相差多少ListNode* shortlist = headA;ListNode* longlist = headB;if(lenA > lenB)//这里用来准确确定长、短链表{shortlist = headB;longlist = headA;}while(gap--)//让长链表走差距步{longlist = longlist->next;}while(longlist != shortlist)//然后长链表和短链表一起走{longlist = longlist->next;shortlist = shortlist->next;}return longlist;}
};

 

4. LeetCode141.环形链表

环形链表 

思路动图:

 

双指针法:

快指针先走两步,紧接着慢指针走

class Solution {
public:bool hasCycle(ListNode *head) {ListNode* fast = head;ListNode* slow = head;while(fast && fast->next){fast = fast->next->next;slow = slow->next;if(fast == slow){return true;}}return false;}
};

5. LeetCode142.环形链表II

环形链表II 

class Solution {
public:ListNode *detectCycle(ListNode *head) {ListNode* fast = head;ListNode* slow = head;while(fast && fast->next){fast = fast->next->next;slow = slow->next;if(fast == slow){ListNode* meet = slow;while(meet != head){meet = meet->next;head = head->next;}return head;}}return nullptr;}
};

6. LeetCode138.复制带随机指针的链表 

 

 

class Solution {
public:Node* copyRandomList(Node* head) {//1.拷贝源节点并链接Node* cur = head;while(cur){Node* copy = new Node(cur->val);copy->next = cur->next;cur->next = copy;cur = copy->next;}cur = head;//2.根据原节点,处理copy节点的randomwhile(cur){Node* copy = cur->next;if(cur->random == nullptr){copy->random = nullptr;}else{copy->random = cur->random->next;}cur = copy->next;}cur = head;//3.把拷贝节点解下来,链接成新链表。同时恢复原链表;Node* copyhead, *copytail;copyhead = copytail = nullptr;while(cur){Node* copy = cur->next;Node* next = copy->next;if(copytail == nullptr){copyhead = copytail = copy;}else{copytail->next = copy;copytail = copy;}cur->next = next;cur = next;}return copyhead;}
};

 


http://www.ppmy.cn/news/8417.html

相关文章

2022年总结

2022年悄无声息的过去了,迎来了2023年。 学生时代的每一年过的都会比较充实,因为有同学和周围优秀的人去推动自己进步。 我是一个不善于表达的人,高中时候优秀的文字功底已经被消耗殆尽,已经写不出什么让人眼前一亮的文字了&#…

超好用!win10安装Eiseg标注软件及使用(CPU版本)

写在前面的话 众所周知,标注分割掩膜的软件一般使用labelme,但是一个一个点太麻烦了,工作量太大,,之前,我的思路就是先标少量的数据然后训练个初始模型,再用初始模型对剩下的图像预测掩膜&…

蓝桥杯寒假集训第四天(全球变暖DFS)

没有白走的路,每一步都算数🎈🎈🎈 题目描述: 有一个正方形区域,里面有大陆和海洋,暂且用‘.’表示海洋,用‘#’表示大陆。我们把上下左右都连在一起的大陆称之为岛屿。但是随着气温…

【Linux】Linux进程的理解

如果不改变自己,就别把跨年搞的和分水岭一样,记住你今年是什么吊样,明年就还会是什么吊样!!! 文章目录一、冯诺依曼体系结构(硬件)二、操作系统(软件)1.操作…

15. 我是怎么用一个特殊 Cookie ,限制住别人的爬虫的

爬虫训练场,第15篇博客。 博客详细清单,参考 https://pachong.vip/blog 本次案例,用定值 Cookie 实现反爬 文章目录Cookie 生成Python Flask 框架生成 CookieFlask make_response 加载模板Flask 判断指定 cookie 是否存在补充知识点Cookie 生…

构造函数和原型

1、概述 在典型的 OOP 的语言中(如 Java),都存在类的概念,类就是对象的模板,对象就是类的实例,但在 ES6之前, JS 中并没用引入类的概念。ES6, 全称 ECMAScript 6.0 ,201…

【数据结构】冒泡排序、快速排序(递归,非递归)、归并排序(递归,非递归),七大排序比较,

文章目录冒泡排序快速排序归并排序七大排序之间的对比冒泡排序 基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小…

基于OpenSSL的安全Web Server实现

目录 一、实验目的 二、实验软硬件要求 三、实验预习 四、实验内容(实验步骤、测试数据等) 实验步骤 1编辑代码 2解决报错 3准备网页 五、实验体会(遇到的问题及解决方法) 六、服务器代码 七、测试网页代码 一、实验目…