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

【算法专题九】链表

文章目录

  • 0.链表常用技巧和操作总结
  • 1.两两相加
    • 1.1 题目
    • 1.2 思路
    • 1.3 代码
  • 2.两两交换链表中的节点
    • 2.1 题目
    • 2.2 思路
    • 2.3 代码
  • 3.leetcode 143.重排链表
    • 3.1 题目
    • 3.2 思路
    • 3.3 代码
  • 4.合并K个升序链表
    • 4.1 题目
    • 4.2 思路
    • 4.3 代码
  • 5.K个一组翻转链表
    • 5.1 题目
    • 5.2 思路
    • 5.3 代码

0.链表常用技巧和操作总结

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

1.两两相加

1.1 题目

题目链接
在这里插入图片描述在这里插入图片描述

1.2 思路

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

1.3 代码

class Solution {
public:ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {ListNode* cur1 = l1, * cur2 = l2;ListNode* newhead = new ListNode(0);ListNode* prev = newhead;int t = 0;while(cur1 || cur2 || t){if(cur1){t += cur1->val;cur1 = cur1->next;}if(cur2){t += cur2->val;cur2 = cur2->next;}prev->next = new ListNode(t % 10);t /= 10;prev = prev->next;}prev = newhead->next;delete newhead;return prev;}  
};

2.两两交换链表中的节点

2.1 题目

题目链接
在这里插入图片描述
在这里插入图片描述

2.2 思路

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

2.3 代码

class Solution {
public:ListNode* swapPairs(ListNode* head) {if(head == nullptr || head->next == nullptr) return head;ListNode* newhead = new ListNode(0);newhead->next = head;ListNode* prev = newhead, * cur = head, * next = head->next, * nnext = next->next;while(cur && next){// 交换节点prev->next = next;next->next = cur;cur->next = nnext;// 移动prev、cur、next、nnextprev = cur;cur = nnext;if(cur) next = cur->next;if(next) nnext = next->next;}prev = newhead->next;delete newhead;return prev;}
};

3.leetcode 143.重排链表

3.1 题目

题目链接
在这里插入图片描述
在这里插入图片描述

3.2 思路

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

3.3 代码

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:void reorderList(ListNode* head) {// 处理边界情况if(head == nullptr || head->next == nullptr || head->next->next == nullptr) return;// 1. 找到链表的中间节点 - 快慢双指针 (一定要画图考虑 slow 的落点在哪里)ListNode* slow = head, *fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;}// 2. 把slow 后面的部分给逆序 - 头插法ListNode* head2 = new ListNode(0);ListNode* cur = slow->next;slow->next = nullptr; // 注意把两个链表给断开while(cur){ListNode* next = cur->next;cur->next = head2->next;head2->next = cur;cur = next;}// 3.合并两个链表 - 双指针ListNode* ret = new ListNode(0);ListNode* prev = ret;ListNode* cur1 = head, *cur2 = head2->next;while(cur1){// 先放第一个链表prev->next =  cur1;cur1 = cur1->next;prev = prev->next;// 再放第二个链表if(cur2){prev->next = cur2;cur2 = cur2->next;prev = prev->next;}}delete head2;delete ret;}
};

4.合并K个升序链表

4.1 题目

题目链接
在这里插入图片描述
在这里插入图片描述

4.2 思路

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

4.3 代码

// 方法1:暴力枚举,时间复杂度应该是超时的,不写代码
// 方法2
class Solution {public:struct cmp{bool operator()(ListNode* l1, ListNode* l2){return l1->val > l2->val;}};ListNode* mergeKLists(vector<ListNode*>& lists) {// 创建一个小根堆priority_queue<ListNode*, vector<ListNode*>, cmp> heap;// 让所有头结点进入小根堆for(auto l : lists)if(l) heap.push(l);// 合并K个有序链表ListNode* newHead = new ListNode(0);ListNode* prev = newHead;while(!heap.empty()){ListNode* t = heap.top();heap.pop();prev->next = t;prev = prev->next;if(t->next) heap.push(t->next);}prev = newHead->next;delete newHead;return prev;}
};
// 方法三:归并 递归方法
class Solution {
public:ListNode* mergeKLists(vector<ListNode*>& lists) {return merge(lists, 0, lists.size() - 1);}ListNode* merge(vector<ListNode*>& lists, int left, int right){// 0. 处理边界情况if(left > right) return nullptr;if(left == right) return lists[left];// 1. 平分数组int mid = (left + right) >> 1;// 2. 递归处理左右区间ListNode* l1 = merge(lists, left, mid);ListNode* l2 = merge(lists, mid + 1, right);// 3. 合并两个有序链表return mergeTwoLists(l1, l2); }ListNode* mergeTwoLists(ListNode* l1, ListNode* l2){// 0. 处理边界情况if(l1 == nullptr) return l2;if(l2 == nullptr) return l1;// 1. 合并两个有序链表ListNode head;ListNode* prev = &head;head.next = nullptr;while(l1 && l2){if(l1->val < l2->val){prev = prev->next = l1;if(l1) l1 = l1->next;}else{prev = prev->next = l2;if(l2) l2 = l2->next;}}// 2. 处理剩余的节点if(l1) prev->next = l1;if(l2) prev->next = l2;return head.next;}
};

5.K个一组翻转链表

5.1 题目

题目链接
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.2 思路

在这里插入图片描述

5.3 代码

class Solution {
public:ListNode* reverseKGroup(ListNode* head, int k) {// 1.先求有几组kint n = 0;ListNode* cur = head;while(cur){cur = cur->next;n++;}n /= k;// 2.然后进行求解cur = head;ListNode* newHead = new ListNode(0);ListNode* prev = newHead;for(int i = 0; i < n; i++){ListNode* tmp = cur;for(int j = 0; j < k; j++){ListNode* next = cur->next;cur->next = prev->next;prev->next = cur;cur = next;}prev = tmp;}// 3.处理剩余的部分prev->next = cur;cur = newHead->next;delete newHead;return cur;}
};
http://www.xdnf.cn/news/268291.html

相关文章:

  • Socket 编程 UDP
  • C++继承基础总结
  • GESP2024年6月认证C++八级( 第三部分编程题(2)空间跳跃)
  • VFS Global 携手 SAP 推动数字化转型
  • Three.js支持模型格式区别、建议
  • <property name=“userDao“ ref=“userDaoBean“/> 这两个的作用和语法
  • Java虚拟线程基础介绍
  • 23.合并k个升序序链表- 力扣(LeetCode)
  • Spring Cloud与Service Mesh集成:Istio服务网格实践
  • 【学习笔记】 强化学习:实用方法论
  • deepseek提供的Red Hat OpenShift Container Platform 4.X巡检手册
  • 深入理解Redis SDS:高性能字符串的终极设计指南
  • 基于Springboot高校网上缴费综合务系统【附源码】
  • CSS元素动画篇:基于当前位置的变换动画(合集篇)
  • 《算法导论(第4版)》阅读笔记:p2-p3
  • Java大师成长计划之第11天:Java Memory Model与Volatile关键字
  • 【Mytais系列】Myatis的设计模式
  • API接口:轻松获取企业联系方式
  • 理解Android Studio IDE工具
  • 虚幻基础:角色朝向
  • MIT6.S081-lab8前置
  • C++ 开发指针问题:E0158 表达式必须为左值或函数指示符
  • UDP 通信详解:`sendto` 和 `recvfrom` 的使用
  • python进阶(1)字符串
  • DeepSeek-Prover-V2-671B:AI在数学定理证明领域的重大突破
  • 随机变量数字特征
  • 第六章,BGP---边界网关协议
  • 【原创】风云扫描王[特殊字符]OCR识别翻译!证件照
  • 202553-sql
  • 信创开发中跨平台开发框架的选择与实践指南