【算法训练-链表 零】链表高频算法题看这一篇就够了

一轮的算法训练完成后,对相关的题目有了一个初步理解了,接下来进行专题训练,以下这些题目就是汇总的高频题目
在这里插入图片描述

题目题干直接给出对应博客链接,这里只给出简单思路、代码实现、复杂度分析

反转链表

依据难度等级分别为反转链表、区间反转链表、K个一组反转链表,【算法训练-链表 一】【反转链表】反转链表、区间反转链表、K个一组反转链表

反转链表【EASY】

LeetCode地址,双指针移动逐个扭转指针方向,关键词:双指针,临时节点
在这里插入图片描述


/*** 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 reverseList(ListNode head) {// 1 入参校验,如果链表为空或者只有一个节点,直接返回if (head == null || head.next == null) {return head;}// 2 定义双指针节点进行遍历反转操作ListNode pre = null;ListNode cur = head;// 3 遍历链表,进行反转操作while (cur!= null) {// 1 定义临时节点存储当前节点的下一个节点ListNode pNext = cur.next;// 2 当前节点断开指向上一个节点cur.next = pre;// 3 双指针向前移动pre = cur;cur = pNext;}// 4 返回尾节点,也就是新的头节点return pre;}
}

时间复杂度:O(N),遍历了一遍链表
空间复杂度:O(1), 额外使用了常数级的指针变量

区间反转链表【MID】

LeetCode地址,双指针到指定位置就位,然后进行区间内的反转操作,关键词:双指针,临时节点,虚拟头节点
在这里插入图片描述


/*** 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 reverseBetween(ListNode head, int left, int right) {// 1 入参校验,如果链表为空或者只有一个节点,直接返回if (head == null || head.next == null) {return head;}// 如果整数left和right相等或者left大于right,直接返回if (left == right || left > right) {return head;}// 2 定义虚拟头节点与双指针,如果头节点也被反转了就丢了,所以需要虚拟头节点ListNode dummyHead = new ListNode(-1);dummyHead.next = head;ListNode pre = dummyHead;ListNode cur = head;// 3 双指针同时向前left-1步走到修改位置for (int i = 1; i < left; i++) {cur = cur.next;pre = pre.next;}// 4 双指针开始在区间内进行反转操作1-2-3-4-5for (int i = left; i < right; i++) {// 记录节点3ListNode pNext = cur.next;// 节点2指向节点4cur.next = pNext.next;// 节点3指向节点2pNext.next = pre.next;// 节点1指向节点3 : 1-3-2-4-5, cur一直指向节点2,pre一直指向节点1,下一轮4和3-2整体交换pre.next = pNext;}// 5 返回区间反转后的链表return dummyHead.next;}
}

时间复杂度:O(N),遍历了一遍链表
空间复杂度:O(1), 额外使用了常数级的指针变量

K个一组反转链表【HARD】

LeetCode地址,递归的将区间进行反转然后进行拼接,关键词:双指针,递归
在这里插入图片描述


/*** 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) {// 1 入参校验,如果链表为空或者只有一个节点或者k小于2,直接返回if (head == null || head.next == null || k < 2) {return head;}// 2 设置区间尾节点等于头节点ListNode tail = head;for (int i = 0; i < k; i++) {// 如果tail为空,说明链表长度小于k,无需反转,直接返回这段子区间的头节点if (tail == null) {return head;}// 如果tail不为空,tail指针向前移动,移动k步,直到移动到下一区间头节点tail = tail.next;}// 3 对区间进行反转操作,返回新的头节点ListNode newHead = reverse(head, tail);// 4 反转后,head变成了当前区间尾节点,tail作为下一子区间头节点传入方法递归,区间连接head.next = reverseKGroup(tail, k);// 5 返回新的头节点return newHead;}// 区间反转链表private ListNode reverse(ListNode head, ListNode tail) {// 1 入参判断,如果链表为空或者只有一个节点,直接返回if (head == null || head.next == null) {return head;}// 2 定义双指针节点进行遍历反转操作ListNode pre = null;ListNode cur = head;// 3 遍历链表,进行反转操作,tail为下一区间的头节点,所以这里是cur != tailwhile (cur != tail) {// 记录当前节点的下一个节点ListNode pNext = cur.next;// 当前节点断开指向上一个节点cur.next = pre;// 双指针向前移动pre = cur;cur = pNext;}// 4 返回尾节点,也就是新的头节点return pre;}
}

时间复杂度:O(N),虽然递归反转,但链表只遍历了一遍
空间复杂度:O(N/K)*O(1),递归的最大栈深度,也就是递归深度 *每次递归的空间复杂度

合并链表

依据难度分为合并两个有序链表以及合并K个有序链表,【算法训练-链表 二】【合并链表】合并两个有序链表、合并K个有序链表

合并两个有序链表【EASY】

LeetCode地址,主要思路就是双指针在两个有序链表上漫游,将较小的依次补全到新的链表上,关键词:双指针
在这里插入图片描述


/*** 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 mergeTwoLists(ListNode list1, ListNode list2) {// 1 入参校验,如果链表为空直接返回if (list1 == null && list2 == null) {return null;}if (list1 == null) {return list2;}if (list2 == null) {return list1;}// 2 定义虚拟头节点和两个漫游指针ListNode dummyHead = new ListNode(-1);ListNode p1 = list1;ListNode p2 = list2;ListNode p = dummyHead;// 3 双指针分别在两个链表漫游while (p1 != null && p2 != null) {// 1 下一个节点挂p1if (p1.val <= p2.val) {p.next = p1;p1 = p1.next;} else {// 2 下一个节点挂p2p.next = p2;p2 = p2.next;}p = p.next;}// 4 如果其中一个链表空了则挂另一个链表if (p1 == null) {p.next = p2;}if (p2 == null) {p.next = p1;}// 5 返回头结点return dummyHead.next;}
}

时间复杂度:O(N+M),分别对两个链表进行了遍历
空间复杂度:O(1), 额外使用了常数级的指针变量

合并K个有序链表【HARD】

LeetCode地址,应用分治的思想,先将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) {return divideMerge(lists, 0, lists.length-1);}// 划分子问题private ListNode divideMerge(ListNode[] lists, int left, int right) {// 1 终止条件,划分到最后的单个链表if (left > right) {return null;}// 2 划分到最小单个链表直接返回if (left == right) {return lists[left];}// 3 合并两个链表int mid = left + (right - left) / 2;return mergeTwoLists(divideMerge(lists, left, mid), divideMerge(lists, mid + 1, right));}// 合并两个有序链表private ListNode mergeTwoLists(ListNode pHead1, ListNode pHead2) {// 1 入参校验,如果链表为空直接返回if (pHead1 == null && pHead2 == null) {return null;}if (pHead1 == null) {return pHead2;}if (pHead2 == null) {return pHead1;}// 2 定义虚拟头节点和两个漫游指针ListNode dummyHead = new ListNode(-1);ListNode p1 = pHead1;ListNode p2 = pHead2;ListNode cur = dummyHead;// 3 双指针分别在两个链表漫游while (p1 != null && p2 != null) {// 1 下一个节点挂p1if (p1.val <= p2.val) {cur.next = p1;p1 = p1.next;} else {// 2 下一个节点挂p2cur.next = p2;p2 = p2.next;}cur = cur.next;}// 4 如果其中一个链表空了则挂另一个链表if (p1 == null) {cur.next = p2;}if (p2 == null) {cur.next = p1;}// 5 返回头结点return dummyHead.next;}
}

时间复杂度:O(NLogN),二分分治进行了LogN次划分,每次遍历时间复杂度为O(N)
空间复杂度:O(LogN), 递归栈深度为LogN

链表查找

依据难度为:查找链表中倒数第K个节点,【算法训练-链表 六】【链表查找】:链表中倒数第k个节点

链表中倒数第k个节点【EASY】

LeetCode地址,解题思路就是应用快慢指针,快指针先于慢指针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 trainingPlan(ListNode head, int cnt) {// 1 入参校验如果head为空或者cnt小于1,返回headif (head == null || head.next == null || cnt < 1) {return head;}// 2 定义快慢指针都指向头结点ListNode fast = head;ListNode slow = head;// 3 快指针先前进cnt步for (int i = 1; i < cnt; i++) {// fast为null,证明给的用例cnt大于链表总长度,返回nullif (fast == null) {return null;}fast = fast.next;}// 4 快慢指针同时前进,当快指针为尾节点时,慢指针位置就是倒数第K个while (fast.next != null) {fast = fast.next;slow = slow.next;}// 5 返回slow的位置return slow;}
}

时间复杂度:O(N),遍历了一遍链表
空间复杂度:O(1), 额外使用了常数级的指针变量

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

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

相关文章

Crypto | Affine password 第二届“奇安信”杯网络安全技能竞赛

题目描述&#xff1a; 明文经过仿射函数y3x9加密之后变为JYYHWVPIDCOZ&#xff0c;请对其进行解密&#xff0c;flag的格式为flag{明文的大写形式}。 密文&#xff1a; JYYHWVPIDCOZ解题思路&#xff1a; 1、使用在线网站直接破解或手工计算破解&#xff0c;获得flag。&#xf…

使用Nginx和uwsgi在自己的服务器上部署python的flask项目

Nginx 是一个高性能的 HTTP 和反向代理服务。其特点是占有内存少&#xff0c;并发能力强&#xff0c;事实上nginx的并发能力在同类型的网页服务器中表现较好。 Nginx 专为性能优化而开发&#xff0c;性能是其最重要的考量指标&#xff0c;实现上非常注重效率&#xff0c;能经受…

4.CentOS7安装MySQL5.7

CentOS7安装MySQL5.7 2023-11-13 小柴你能看到嘛 哔哩哔哩视频地址 https://www.bilibili.com/video/BV1jz4y1A7LS/?vd_source9ba3044ce322000939a31117d762b441 一.解压 tar -xvf mysql-5.7.26-linux-glibc2.12-x86_64.tar.gz1.在/usr/local解压 tar -xvf mysql-5.7.44-…

lc307.区域和检索 - 数组可修改

暴力解法 创建方法&#xff0c;通过switch-case判断所需要调用的方法。 public class RegionsAndSertches {public static void main(String[] args) {String[] str new String[]{"NumArray", "sumRange", "update", "sumRange"};i…

基于RK3568的跑步机方案

I 方案简介 一、跑步机的来历 跑步机是家庭及健身房常备的健身器材&#xff0c;而且是当今家庭健身器材中最简单的一种&#xff0c;是家庭健身器的最佳选择。1965年北欧芬兰唐特力诞生了全球第一台家用的跑步机&#xff0c;设计师根据传速带的原理改变而成。 二、…

人工智能基础_机器学习026_L1正则化_套索回归权重衰减梯度下降公式_原理解读---人工智能工作笔记0066

然后我们继续来看套索回归,也就是线性回归,加上了一个L1正则化对吧,然后我们看这里 L1正则化的公式是第二个,然后第一个是原来的线性回归,然后 最后一行紫色的,是J= J0+L1 对吧,其实就是上面两个公式加起来 然后我们再去看绿色的 第一行,其实就是原来线性回归的梯度下降公式…

Vatee万腾科技决策力的引领创新:Vatee数字化视野的崭新天地

在数字时代的激烈竞争中&#xff0c;Vatee万腾以其科技决策力的引领&#xff0c;开创了数字化视野的崭新天地。这并不仅仅是一场技术的飞跃&#xff0c;更是一次对未来的深刻洞察和引领创新的勇敢实践。 Vatee万腾的科技决策力不仅仅停留在数据分析和算法的运用&#xff0c;更是…

BlendTree动画混合算法详解

【混合本质】 如果了解骨骼动画就知道&#xff0c;某一时刻角色的Pose是通过两个邻近关键帧依次对所有骨骼插值而来&#xff0c;换句话说就是由两个关键帧混合而来。 那么可不可以由多个关键帧混合而来呢&#xff1f;当然可以。 更多的关键帧可以来自不同的动画片段&#xf…

nacos适配达梦数据库

一、下载源码 源码我直接下载gitee上nacos2.2.3的&#xff0c;具体链接&#xff1a;https://gitee.com/mirrors/Nacos/tree/2.2.3&#xff0c;具体如下图&#xff1a; 二、集成达梦数据库驱动 解压源码包&#xff0c;用idea打开源码&#xff0c;等idea和maven编译完成&#xff…

小程序中如何设置多门店/多人/多商品价格库存等复杂场景设置

有些商家希望打造小程序平台&#xff0c;在这个平台上有多个商家入驻&#xff0c;他们分别售卖自己的商品。而有些商家有多个连锁店&#xff0c;连锁店的商品都是一样的&#xff0c;但不同的连锁店有不同的库存和价格。这些业务在采云小程序中是怎么支持的呢&#xff1f;下面具…

使用 `open-uri.with_proxy` 方法打开网页

Ruby 爬虫程序如下&#xff1a; require open-uri require nokogiri# 定义代理信息 proxy_host jshk.com.cn# 定义要爬取的网页 URL url http://www.example.com# 使用代理信息打开网页 open-uri.with_proxy(proxy_host, proxy_port) do |proxy|# 使用 Nokogiri 库解析网页内…

web前端开发第3次Dreamweave课堂练习/html练习代码《网页设计语言基础练习案例》

目标图片&#xff1a; 文字素材&#xff1a; 网页设计语言基础练习案例 ——几个从语义上和文字相关的标签 * h标签&#xff08;h1~h6&#xff09;&#xff1a;用来定义网页的标题&#xff0c;成对出现。 * p标签&#xff1a;用来设置网页的段落&#xff0c;成对出现。 * b…

微信小程序授权登陆 getUserProfile

目录 前言 步骤&#xff1a; 示例代码: 获取用户信息的接口变化历史: 注意事项&#xff1a; 前言 在微信小程序中&#xff0c;你可以使用 getUserProfile 接口来获取用户的个人信息&#xff0c;并进行授权登录。以下是使用 getUserProfile 的步骤&#xff1a; 小程序发了…

file2Udp增量日志转出Udp简介

https://gitee.com/tianjingle/file2udp 很多时候服务产生的日志需要进行汇总&#xff0c;这种统一日志处理的方式有elb&#xff0c;而且很多日志组件也支持日志转出的能力。但是从广义上来说是定制化的&#xff0c;我们需要一个小工具实现tail -f的能力&#xff0c;将增量日志…

U-Mail邮件中继有效解决海外邮件发送不畅难题

相信不少企业都经历过类似的问题&#xff0c;在跟国外客户发送电子邮件的过程中&#xff0c;经常会遇到邮件发不过去、邮件隔了很久对方才收到&#xff0c;或者是邮件退信等情况出现。对此&#xff0c;U-Mail技术专家李工解释到&#xff0c;导致海外通邮不畅主要有以下三个原因…

ADFS 高可用配置 + NLB配置(Windows网络负载均衡)

ADFS 高可用配置 NLB配置&#xff08;Windows网络负载均衡&#xff09; ADFS安装配置NLB配置节点 TEST-ADFS-01 网络负载平衡配置节点 TEST-ADFS-02 网络负载平衡修改CRM配置 ADFS实现高可用负载均衡有两种&#xff0c;主要是在数据库的选择方式&#xff1a; windows自带的内…

2023.11.11通过html内置“required-star“添加一个红色的星号来表示必填项

2023.11.11通过html内置"required-star"添加一个红色的星号来表示必填项 在HTML中&#xff0c;可以使用标签来为元素添加说明。同时可以通过添加一个红色的星号来表示必填项。 <!DOCTYPE html> <html lang"en"> <head><meta charse…

Python中的数据增强技术

使用imgaug快速观察Python中的数据增强技术 在本文中&#xff0c;我们将使用imgaug库来探索Python中不同的数据增强技术 什么是图像增强 图像增强是一种强大的技术&#xff0c;用于在现有图像中人为地创建变化以扩展图像数据集。这是通过应用不同的变换技术来实现的&#xf…

EXTI (2)

增强版实验简介 EXTI5和EXTI9共享一个中断源 下面的类似 EXTI0到4各自拥有一个中断源 改变引脚 PA0和PA1改变为PA5 和PA6 EXTI的重映射 之前是把PA0映射到EXTI0 PA1映射到EXTI1上 现在是要把PA5和PA6分别映射到EXTI5和6上 EXTI进行初始化 NVIC初始化 编写中断函数 因为EXTI…

如何在电脑和手机设备上编辑只读 PDF

我们大多数人更喜欢以 PDF 格式共享和查看文件&#xff0c;因为它更专业、更便携。但是&#xff0c;通常情况下您被拒绝访问除查看之外的内容编辑、复制或评论。如果您希望更好地控制您的 PDF 或更灵活地编辑它&#xff0c;请弄清楚为什么您的 PDF 是只读的&#xff0c;然后使用…