算法系列--链表刷题(二)

💕"轻舟已过万重山"💕
作者:Mylvzi
文章主要内容:算法系列–链表刷题(二)
在这里插入图片描述

今天为大家带来的是算法系列--链表刷题(二),带来了几道经典的有关链表的面试题(合并K个有序列表)

1.两数相加

https://leetcode.cn/problems/add-two-numbers/

模拟两数相加:

使用两个指针cur1和cur2来遍历两个链表,通过t记录每次相加的结果,最后创建出新的节点,尾插

注意:

  1. 每次相加时都需要更新t的值,但是不可以直接将t设置为0,因为存在进位的可能,比如t = 9 + 9 = 18,要插入节点的val = 8,还要记录进位1,所以:val = t % 10, t /= 10
  2. 循环的结束要同时满足三个条件,cur1 = null, cur2 = null, t = 0,其中最后t = 0这种情况最容易忘记,导致最后需要进位没进位成,结果相比于正确答案少了一位
    代码:
/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {ListNode cur1 = l1;ListNode cur2 = l2;ListNode phead = new ListNode(0);ListNode cur = phead;// 用于尾插int t = 0;// 用于表示本次相加的结果  处理进位// 要注意t最后可能不为0 要进一位while(cur1 != null || cur2 != null || t != 0) {// 加上第一个节点if(cur1 != null) {t += cur1.val;cur1 = cur1.next;}// 加上第二个节点if(cur2 != null) {t += cur2.val;cur2 = cur2.next;}ListNode newNode = new ListNode(t % 10);t /= 10;// 尾插cur.next = newNode;cur = newNode;}return phead.next;}
}

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

https://leetcode.cn/problems/swap-nodes-in-pairs/description/

思路:

  1. 分别得到下标为奇数的所有节点的组合和下标为偶数的所有节点的组合(下标从1开始)
  2. 按照偶数节点在前,奇数节点在后的顺序合并两个链表
  3. 得到新的链表

代码实现:

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode swapPairs(ListNode head) {if(head == null || head.next == null) return head;// 定义两个虚拟节点 分别接收奇数和偶数的节点ListNode p1 = new ListNode(0);ListNode p2 = new ListNode(0);ListNode cur1 = p1;ListNode cur2 = p2;ListNode cur = head;int i = 1;// 分别得到奇数和偶数的链表组合while(cur != null) {ListNode newNode = new ListNode(cur.val);if(i % 2 != 0) {// 奇数cur1.next = newNode;cur1 = newNode;}else {// 偶数cur2.next = newNode;cur2 = newNode;}cur = cur.next;i++;}// 合并两个链表ListNode p3 = new ListNode(0);ListNode t1 = p1.next;ListNode t2 = p2.next;ListNode cur3 = p3;while(t1 != null || t2 != null) {if(t2 != null) {cur3.next =  t2;cur3 = t2;t2 = t2.next;}if(t1 != null) {cur3.next =  t1;cur3 = t1;t1 = t1.next;}}return p3.next;}
}

注:本题更加简洁的写法是通过递归实现的,感兴趣的可以去我的算法系列里查看

3.重排链表

https://leetcode.cn/problems/reorder-list/

思路:

  1. 首先获得中间节点,以中间节点为基准,分为两个不同的链表l1和l2
  2. 逆序l2
  3. 合并两个链表

在这里插入图片描述

代码:

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public void reorderList(ListNode head) {ListNode slow = head, fast = head;// 找到中间节点while(fast != null && fast.next != null) {slow = slow.next;fast = fast.next.next;}ListNode l1 = head;ListNode l2 = slow.next;slow.next = null;// 逆序第二个节点l2 = reverseList(l2);ListNode phead = new ListNode(0);ListNode cur = phead;// 合并两个链表while(l1 != null || l2 != null) {if(l1 != null) {cur.next = l1;cur = l1;l1 = l1.next;}if(l2 != null) {cur.next = l2;cur = l2;l2 = l2.next;}}head = phead.next;}public ListNode reverseList(ListNode head) {if(head == null) return null;if(head.next == null) return head;ListNode pHead = new ListNode(0);ListNode cur = head;while(cur != null) {ListNode curNext = cur.next;cur.next = pHead.next;pHead.next = cur;cur = curNext;}return pHead.next;}
}

同样的本题也有更加简洁的递归写法

4.合并 K 个升序链表(hard)

链接:
https://leetcode.cn/problems/merge-k-sorted-lists/description/

分析:

思路一:利用优先级队列

其实本题和合并两个有序链表很相似,可以看做是上一题的plus版本

虽然这里是合并K个有序链表,但是我们可以借鉴合并两个有序链表的思路,`创建一个傀儡节点,找到两个链表节点的最小值,依次插入到傀儡节点之后

这里的难点在于如果只有两个节点,我们可以直接比较,但是现在有K个节点,如何快速地找到K个节点的最小值呢?使用优先级队列,利用优先级队列将K个链表的头结点存入到优先级队列之中,由于默认是小根堆,所以堆顶元素就是K个链表头结点的最大值,将其插入到傀儡节点之后,更新傀儡节点,然后插入堆顶节点的下一个节点,接着判断最小值,重复上述过程

手写:
在这里插入图片描述
代码:

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode mergeKLists(ListNode[] lists) {PriorityQueue<ListNode> heap = new PriorityQueue<>((o1,o2) ->o1.val - o2.val);ListNode ret = new ListNode(0);ListNode phead = ret;for(ListNode head : lists)// 将链表的头结点存入堆中if(head != null)heap.offer(head);while(!heap.isEmpty()) {ListNode tmp = heap.poll();phead.next = tmp;phead = tmp;if(tmp.next != null) heap.offer(tmp.next);// 注意下一个节点可能为空}return ret.next;}
}

思路二:利用归并的思想

其实这道题非常符合分治归并的思想,题目相当于给了我们一个比较特殊的数组(数组的元素是链表),实际上最重要完成的工作就是对这K个元素进行从小到大的排序,既然是排序我们就可以使用归并的思想,为什么想到归并呢?这是经过分析得到的,实际上我们是对一个一个的链表进行合并+排序操作的,这一步其实就是归并中分解到最小单元,开始回并的过程啊!所以可以使用归并的思想解决

代码:

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode mergeKLists(ListNode[] lists) {if(lists == null || lists.length == 0) return null;// 采用归并的思想解决return merge(lists,0,lists.length-1);}public ListNode merge(ListNode[] lists,int left,int right) {// 递归出口if(left >= right) return lists[left];int mid = (left + right) /2;ListNode l1 = merge(lists,left,mid);ListNode l2 = merge(lists,mid + 1,right);return mergeTwoLists(l1,l2);}// 合并两个有序链表public ListNode mergeTwoLists(ListNode list1, ListNode list2) {// 递归if(list1 == null) return list2;if(list2 == null) return list1;if(list1.val < list2.val) {list1.next = mergeTwoLists(list1.next,list2);return list1;}else {list2.next = mergeTwoLists(list2.next,list1);return list2;}}
}

5.K个⼀组翻转链表

链接:
https://leetcode.cn/problems/reverse-nodes-in-k-group/description/

分析:

本题采用模拟的思想,具体的模拟策略如下:

  1. 求出要反转多少个长度为K的链表–n
  2. 翻转n次即可

在这里插入图片描述
代码:

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode reverseKGroup(ListNode head, int k) {// 求需要翻转的组数nint cnt = 0;ListNode tmp = head;while(tmp != null) {cnt++;tmp = tmp.next;}int n = cnt / k;// 开始进行翻转ListNode ret = new ListNode(0);ListNode phead = ret;ListNode cur = head;for(int i = 0; i < n; i++) {ListNode prev = cur;// 保存当前翻转链表的头结点for(int j = 0; j < k; j++) {ListNode curnext = cur.next;cur.next = phead.next;phead.next = cur;cur = curnext;}phead = prev;// 每翻转完一组就更新phead}phead.next = cur;return ret.next;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/766695.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

测试ALPHA开发板CAN1的设备树文件

一. 简介 前面一篇文章学习了 ALPHA开发板上的 CAN接口的设备节点信息&#xff0c;文章如下&#xff1a; ALPHA开发板修改CAN的设备树节点信息-CSDN博客 本文对设备树文件进行测试&#xff0c;即开发板加载 .dtb设备树文件。 二. 加载测试 CAN的设备树文件 1. 拷贝设备树…

fiddler过滤器使用,隐藏图片、js、css请求

如果抓包过程中不想查看图片、js、css请求&#xff0c;或者只想抓某个ip或者某个网页下的请求&#xff0c;可以在过滤器中设置。 &#xff08;1&#xff09;没有开启过滤器 可以看出所有的请求都会抓取&#xff0c;cs、js、图片请求都有 &#xff08;2&#xff09;开启过滤器 …

dubbo 源码系列之-集群三板斧---负载均衡(二)

在上一课时我们了解了 LoadBalance 接口定义以及 AbstractLoadBalance 抽象类的内容&#xff0c;还详细介绍了 ConsistentHashLoadBalance 以及 RandomLoadBalance 这两个实现类的核心原理和大致实现。本课时我们将继续介绍 LoadBalance 的剩余三个实现。 LeastActiveLoadBala…

MySQL | 视图

视图是一个虚拟表&#xff0c;其内容由查询定义。同真实的表一样&#xff0c;视图包含一系列带有名称的列和行数据。视图的数据变化会影响到基表&#xff0c;基表的数据变化也会影响到视图。 1. 基本使用 1.1. 创建视图 create view 视图名 as select语句&#xff1b; 创建测…

hcip实验

一、实验拓扑 二、实验划分 AR1的Serial3/0/0接口&#xff1a;192.168.1.1/24&#xff1b; AR2的Serial3/0/0接口&#xff1a;192.168.1.2/24&#xff1b; AR2的Serial3/0/1和4/0/0的聚合接口&#xff1a;192.168.2.2/24&#xff1b; AR3的Serial3/0/0和3/0/1的聚合接口&am…

网络安全实训Day8

写在前面 网络工程终于讲完了。这星期到了网络安全技术部分。 网络安全实训-网络安全技术 网络安全概述 信息安全&#xff1a;所有保障计算机硬件、系统、软件、数据不因有意或无意的行为导致的服务中断、数据损坏或丢失等安全事件的保障技术 网络安全&#xff1a;基于计算机…

C/C++之内存旋律:星辰大海的指挥家

个人主页&#xff1a;日刷百题 系列专栏&#xff1a;〖C/C小游戏〗〖Linux〗〖数据结构〗 〖C语言〗 &#x1f30e;欢迎各位→点赞&#x1f44d;收藏⭐️留言&#x1f4dd; ​ ​ 一、C/C内存分布 我们先来了解一下C/C内存分配的几个区域&#xff0c;以下面的代码为例来看…

机器学习——决策树剪枝算法

机器学习——决策树剪枝算法 决策树是一种常用的机器学习模型&#xff0c;它能够根据数据特征的不同进行分类或回归。在决策树的构建过程中&#xff0c;剪枝算法是为了防止过拟合&#xff0c;提高模型的泛化能力而提出的重要技术。本篇博客将介绍剪枝处理的概念、预剪枝和后剪…

C语言内存函数(1)【memcpy函数的使用与模拟实现】【memmove函数的使用和模拟实现】

关于内存函数有四个函数需要我们学习。分别是memcpy&#xff0c;memmove&#xff0c;memset和memcmp。都在头文件string.h里面。 一.memcpy函数的使用 一提到这个函数&#xff0c;我们可能会联想到strcpy函数&#xff0c;但strcpy函数是针对字符串的拷贝。但是我们在写代码的…

百度文心一言(ERNIE bot)API接入Android应用

百度文心一言&#xff08;ERNIE bot&#xff09;API接入Android应用实践 - 拾一贰叁 - 博客园 (cnblogs.com) Preface: 现在生成式AI越来越强大了&#xff0c;想在android上实现一个对话助手的功能&#xff0c;大概摸索了一下接入百度文心一言API的方法。 与AI助手交换信息的…

C++类的6个默认成员函数(构造)

C类和对象基础-CSDN博客https://blog.csdn.net/lh11223326/article/details/136834917?spm1001.2014.3001.5501 目录 1.构造函数 概念 特性 2.析构函数 概念 特性 3.拷贝构造函数 概念 特征 4.赋值运算符重载&#xff08;构造实现&#xff09; 运算符重载 赋值运算…

Kafka快速入门及使用

入门 官网 简介 Kafka是一个分布式的流媒体平台应用&#xff1a; 消息系统日志收集用户行为追踪流式处理 特点 高吞吐量消息持久化高可靠性高扩展性 常用术语 Broker&#xff1a;集群中的服务器Zookeeper&#xff1a;服务管理Topic&#xff1a;主题&#xff0c;Kafka发…

Linux/openEuler系统部署spring boot+vue前后端分离项目(nginx均衡代理)

Linux/openEuler系统部署spring bootvue前后端分离项目&#xff08;nginx均衡代理&#xff09; 1、系统环境准备&#xff0c;安装openjdk和nginx还有MySQL&#xff0c;咱们本文先连接主机mysql进行登录&#xff08;linux上的mysql服务可以先不安装&#xff09; 可以看我前面的…

springboot精品源码

springboot精品源码 所有项目都包括&#xff1a;源码数据库文件开题LW说明文档运行视频 请看主页资料联系。 项目类型包括: 1 SpringBoot学生心理咨询评估系统 2 基于SpringBoot的网上订餐系统 3 大学生租房平台的设计与实现 4 SpringBoot房屋租赁系统 5 基于SpringBoot的课…

SpringCloud之网关组件Gateway学习

SpringCloud之网关组件Gateway学习 GateWay简介 Spring Cloud Gateway是Spring Cloud的⼀个全新项目&#xff0c;目标是取代Netflix Zuul&#xff0c;它基于Spring5.0SpringBoot2.0WebFlux&#xff08;基于高性能的Reactor模式响应式通信框架Netty&#xff0c;异步⾮阻塞模型…

STM32---DHT11温湿度传感器与BH1750FVI光照传感器(HAL库、含源码)

写在前面&#xff1a;本节我们学习使用两个常见的传感器模块&#xff0c;分别为DHT11温湿度传感器以及BH1750FVI光照传感器,这两种传感器在对于环境监测中具有十分重要的作用&#xff0c;因为其使用简单方便&#xff0c;所以经常被用于STM32的项目之中。今天将使用分享给大家&a…

HTML5和CSS3笔记

一&#xff1a;网页结构(html)&#xff1a; 1.1&#xff1a;页面结构&#xff1a; 1.2&#xff1a;标签类型&#xff1a; 1.2.1&#xff1a;块标签&#xff1a; 1.2.2&#xff1a;行内标签&#xff1a; 1.2.3&#xff1a;行内块标签&#xff1a; 1.2.4&#xff1a;块标签与行…

如何用VSCode和Clangd与Clang-Format插件高效阅读Linux内核源码及写驱动

一、如何高效阅读Linux源码&#xff1a;基于clangd uboot/busybox等都可以用这种方式&#xff0c;理论上说所有基于Make和Cmake的源码工程都可以用这套方案 阅读Linux源码最大问题在于调用链太复杂&#xff0c;一个函数或变量引用太多&#xff0c;source insight和cscope等基于…

Pink老师Echarts教学笔记

可视化面板介绍 ​ 应对现在数据可视化的趋势&#xff0c;越来越多企业需要在很多场景(营销数据&#xff0c;生产数据&#xff0c;用户数据)下使用&#xff0c;可视化图表来展示体现数据&#xff0c;让数据更加直观&#xff0c;数据特点更加突出。 01-使用技术 完成该项目需…

阿里云服务器(Ubuntu22)上的MySQL8数据库下载,安装和远程连接

最近阿里云centos主机到期了改为使用Ubuntu操作系统&#xff0c;在上面安装mysql并远程连接出现了一系列问题并解决。 之前在centos系统上下载mysql8的教程如下&#xff1a; 阿里云服务器&#xff08;centos7&#xff09;上的MySQL8数据库下载&#xff0c;安装和远程连接 主机操…