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

我爱学算法之—— 链表

一、两数相加

题目解析

在这里插入图片描述

这道题,给定两个非空的链表,表示两个非负的整数;其中每位数字都是按照逆序方式存储的。

现在,我们要计算这两个非负整数的和,并以同样的形式返回一个链表。

算法思路

整体来说,这道题还是非常简单的;

因为给定的数字是按照逆序方式存储的,无非就是按照加法的流程进行计算,然后处理进位和新增节点即可。

思路

模拟加法的过程,处理进位、构建结果链表。

代码实现

class Solution {
public:ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {ListNode* head = new ListNode(0);ListNode* cur = head;int tmp = 0; // 进位while (l1 && l2) {int x = l1->val + l2->val + tmp;cur->next = new ListNode(x % 10);cur = cur->next;tmp = x / 10;l1 = l1->next;l2 = l2->next;}while (l1) {int x = l1->val + tmp;cur->next = new ListNode(x % 10);cur = cur->next;tmp = x / 10;l1 = l1->next;}while (l2) {int x = l2->val + tmp;cur->next = new ListNode(x % 10);cur = cur->next;tmp = x / 10;l2 = l2->next;}if (tmp)cur->next = new ListNode(tmp);ListNode* ret = head->next;delete head;return ret;}
};

二、两两交换链表中的节点

题目解析

在这里插入图片描述

给定一个链表,现在要将链表中的节点,两两交换,然后返回交换后的链表。(进行节点交换,而不是值交换)

算法思路

对于交换链表中两个节点,还是非常简单的,只要标注一下所有要用到的节点,就无需考虑先后顺序,直接修改指针指向即可。

但是,这道题我们要注意:

第一个节点也要进行交换,交换之后,它就变成了第二个节点,并指向后面节点;此时就会丢掉一个节点

所以,我们需要创建一个虚拟头节点,来当作交换链表的头节点,这样最终等到的链表才是完整的。

代码实现

class Solution {
public:ListNode* swapPairs(ListNode* head) {ListNode* ret_head = new ListNode(0);ret_head->next = head;ListNode* prev = ret_head;while (prev->next && prev->next->next) {ListNode* node1 = prev->next;ListNode* node2 = prev->next->next;ListNode* next = prev->next->next->next;prev->next = node2;node2->next = node1;node1->next = next;prev = node1;}ListNode* ret = ret_head->next;delete ret_head;return ret;}
};

三、重排链表

题目解析

在这里插入图片描述

这道题,给定一个链表L0、L1、L2... Ln,要求我们重排链表,将链表变成L1、Ln、L2、Ln-1...

算法思路

这道题,整体思路就是模拟,模拟一下重排链表的过程即可。

  • 找到链表中间节点:快慢指针
  • 反转后半部分的链表:头插法
  • 合并两个链表

代码实现

class Solution {
public:void reorderList(ListNode* head) {if (head == nullptr || head->next == nullptr)return;ListNode* fast = head;ListNode *slow = head, *prev = head;while (fast && fast->next) {fast = fast->next->next;prev = slow;slow = slow->next;}prev->next = nullptr;// 逆置后半部分链表ListNode* phead = new ListNode(0);ListNode* cur = phead;// 头插法while (slow) {ListNode* next = slow->next;slow->next = cur->next;cur->next = slow;slow = next;}// 合并两个链表ListNode* cur1 = phead->next;ListNode* cur2 = head->next;cur = head;while (cur1 && cur2) {cur->next = cur1;cur1 = cur1->next;cur->next->next = cur2;cur2 = cur2->next;cur = cur->next->next;}if (cur1)cur->next = cur1;delete phead;}
};

四、合并 K 个升序链表

题目解析

在这里插入图片描述

给定k个升序链表,题目要求我们合并这k个升序链表,然后返回合并好的链表。

算法思路

对于这道题,我们知道如何合并两个有序链表,那和并k个有序链表,无非就是多进行几次操作而已;

暴力合并两个有序链表

依次合并两个有序链表。(会超时)

对于这道题,我们可以使用堆这一数据结构,将所有链表的头节点都放到一个小根堆里去(比较大小的方式就按照其中存储的值比较);

这样每次从堆顶取数值最小的节点,然后将其下一个节点放到堆中。(nullptr不放入堆中)

建小根堆

建立小根堆,存储链表节点;使用vector容器存储即可;实现仿函数,完成链表节点的比较大小。

合并链表

从堆顶取节点,尾插到新链表中,如果其下一个节点不为nullptr,就将其下一个节点放到堆中。

重复上述操作,直到堆中没有节点。

代码实现

class Solution {
public:struct tmp {bool operator()(ListNode* l1, ListNode* l2) {if (l1 && l2)return l1->val > l2->val;elsereturn false;}};ListNode* mergeKLists(vector<ListNode*>& lists) {priority_queue<ListNode*, vector<ListNode*>, tmp> pq;for (auto& e : lists) {if (e != nullptr)pq.push(e);}ListNode* head = new ListNode(0);ListNode* cur = head;while (!pq.empty()) {// 取堆顶节点ListNode* top = pq.top();pq.pop();// 尾插cur->next = top;cur = top;if (top->next)pq.push(top->next);}ListNode* ret = head->next;delete head;return ret;}
};

五、K 个一组翻转链表

题目解析

在这里插入图片描述

这道题给定一个链表和一个整数k,要求我们以k个节点为一组,翻转链表,如果最后节点不足k个,就保留。

算法思路

  • 计算需要翻转链表的组数

对于这道题,首先要做的就是计算需要翻转链表的组数;(题目要求,最后不足k个时,要保持原有顺序

  • 使用头插法,反转k个节点的链表

知道了需要翻转链表的组数,然后就是翻转一组(也就是k个节点);

这里利用头插法返回k个节点。

  • 最后,将不足k个节点的组直接放到结果链表的最后。

代码实现

class Solution {
public:ListNode* reverseKGroup(ListNode* head, int k) {int n = 0;ListNode* cur = head;while (cur) {n++;cur = cur->next;}n /= k;cur = head;ListNode* ret_head = new ListNode(0);ListNode* tail = ret_head;for (int i = 0; i < n; i++) {ListNode* tmp = cur;int j = 0;while (j < k) {// 头插ListNode* next = cur->next;cur->next = tail->next;tail->next = cur;cur = next;j++;}tail = tmp;}tail->next = cur;ListNode* ret = ret_head->next;delete ret_head;return ret;}
};

本篇文章到这里就结束了,感谢支持
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws

http://www.dtcms.com/a/603040.html

相关文章:

  • C++11:引用折叠,完美转发,可变参数模板,defult和delete,final和override,委托构造函数,继承构造函数
  • Datawhale25年11月组队学习:hello-agents+Task2
  • 怎么用php源代码做网站私人网页服务器
  • 天台网站建设题库网站怎样做
  • 如何制作一个php网站源码网上商店的业务流程
  • 网站开发 微信 支付召开网站群建设通知
  • JPA 数据绑定通过 **注解映射** 实现对象与表的关联
  • VSCode编译C语言 | 高效配置与运行步骤指南
  • 怎么建立一个网站放图片夸克浏览器官网入口
  • PPT插入的图片太大了,怎么缩小一点?
  • 网站社区建设公司网站做的好的公司
  • 石家庄建网站挣钱优帮云温州建设集团网站
  • 镜像多阶段构建-YAML-Compose
  • 每日一题 —— [NOIP 2007 普及组] 纪念品分组
  • 如何用wordpress建站自动搭建网站源码
  • 长沙竞价网站建设价格福田深圳网站建设
  • 查企业资质上什么网站网页源代码查找指定文字
  • 重庆蒲公英网站建设公司怎么样网络营销是什么 能做什么
  • c语言反编译工具 | 探讨C语言反编译工具的应用与发展趋势
  • 关系的网站织梦网站怎样做子域名
  • 最牛网站设计公司门户首页网站建设方案
  • 网站建设 seojsc易企秀类似的软件
  • LODE(Loss Decoupling)个人理解
  • 成都网站建设3六六俄罗斯门户网站
  • 淮南房地产网站建设网站睿思设计
  • 十七、自然语言处理概述
  • 微信手机网站流程湖南软件定制开发
  • 如何做自己产品网站企业网站建设杭州公司
  • C++ 离散化
  • 人力资源网站怎么做品牌网站设计公司价格