反转链表

news/2024/11/19 20:31:04/文章来源:https://www.cnblogs.com/zhaoqi94/p/18290871

目录
  • L206 反转链表
      • 题目描述
      • 题解
        • 方法一:迭代
        • 方法二:递归
  • L92 反转链表 II
      • 题目描述
      • 题解
        • 方法一:一遍扫描
        • 方法二:穿针引线
  • L25 K个一组反转链表
      • 题目描述
      • 题解
        • 方法一:模拟

L206 反转链表

题目描述

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例1:

img

示例2:

img

题解

方法一:迭代

假设链表为 1→2→3→∅,我们想要把它改成 ∅←1←2←3。

我们考虑遍历链表,将每个节点的next指针改为指向前一个节点。但是链表是单向的,当遍历到某个节点时,我们已经没有前一个节点的引用了,所以需要使用一个prev引用来保存当前节点的前一个节点。

然后做以下迭代步骤:

  • 保存curr的next引用
  • 设置当前节点的next指向prev
  • 将prev指向当前节点
  • 将curr指向next
class Solution {public ListNode reverseList(ListNode head) {ListNode curr = head;ListNode prev = null;while (curr != null) {ListNode next = curr.next;curr.next = prev;prev = curr;curr = next;}return prev;}
}

复杂度分析

时间复杂度:O(N),遍历一次。

空间复杂度:O(1)

方法二:递归

假设链表为:

n1→…→n**k−1→n**kn**k+1→…→n**m→∅

若从节点 n**k+1 到 n**m 已经被反转,而我们正处于 n**k

n1→…→n**k−1→n**kn**k+1←…←n**m

我们希望 n**k+1 的下一个节点指向 n**k

所以,n**k.next.next=n**k

需要注意的是:

  • next指针的修改
  • 反转后的链表的链尾节点的next应该为null
  • 在递归过程中应该要将反转后的链表头节点返回
class Solution {public ListNode reverseList(ListNode head) {if (head == null || head.next == null) {return head;}ListNode newHead = reverseList(head.next);head.next.next = head;head.next = null;return newHead;}
}

复杂度分析

时间复杂度:O(N)

空间复杂度:O(N),因为递归占用栈空间

L92 反转链表 II

题目描述

给你单链表的头指针 head 和两个整数 leftright ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表

示例1:

img

输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]

示例2:

输入:head = [5], left = 1, right = 1
输出:[5]

题解

方法一:一遍扫描

将链表分成三段,反转中间的部分,然后将左中右重新相接。

下载

下载 (1)

class Solution {public ListNode reverseBetween(ListNode head, int left, int right) {ListNode dummy = new ListNode(0, head);// 0.整个链表分为左中右三段// 1.首先找到左链表的尾部ListNode node = dummy;for (int i = 1; i < left; i++) {node = node.next;}ListNode leftListTail = node;// 2.反转中间链表node = node.next;ListNode midListHead = node;ListNode prev = null;for (int i = left; i <= right; i++) {ListNode next = node.next;node.next = prev;prev = node;node = next;}// 3.重新相接leftListTail.next = prev;midListHead.next = node;return dummy.next;}
方法二:穿针引线

pre永远指向左链表的最后一个节点。

curr永远指向右链表的第一个节点。

每次迭代:

  • 先将 curr 的下一个节点记录为 next
  • 执行操作 ①:把 curr 的下一个节点指向 next 的下一个节点
  • 执行操作 ②:把 next 的下一个节点指向 pre 的下一个节点
  • 执行操作 ③:把 pre 的下一个节点指向 next

image.png

class Solution {public ListNode reverseBetween(ListNode head, int left, int right) {// 设置 dummyNode 是这一类问题的一般做法ListNode dummyNode = new ListNode(-1);dummyNode.next = head;ListNode pre = dummyNode;for (int i = 0; i < left - 1; i++) {pre = pre.next;}ListNode cur = pre.next;ListNode next;for (int i = 0; i < right - left; i++) {next = cur.next;cur.next = next.next;next.next = pre.next;pre.next = next;}return dummyNode.next;}
}

L25 K个一组反转链表

题目描述

给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

示例1

img

输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]

示例2

img

输入:head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]

题解

方法一:模拟

思路就是先向后遍历k个节点,如果剩余元素个数少于k个,则直接返回;如果大于等于k个,就进行翻转。

反转完成之后,需要重新将它接回原链表。

class Solution {public ListNode reverseKGroup(ListNode list, int k) {ListNode dummy = new ListNode(0, list);ListNode tail = dummy;while (true) {ListNode curr = tail;for (int i = 0; i < k; i++) {curr = curr.next;if (curr == null) {return dummy.next;}}ListNode nextKGroupHead = curr.next;ListNode currKGroupHead = tail.next;ListNode prev = nextKGroupHead;curr = tail.next;while (curr != nextKGroupHead) {ListNode nxt = curr.next;curr.next = prev;prev = curr;curr = nxt;}tail.next = prev;tail = currKGroupHead;}}
}

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

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

相关文章

springboot 进程已结束,退出代码为 0

原文:https://blog.csdn.net/lvoelife/article/details/134129860 在pom.xml中,添加<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>然后用maven,重新加载项目…

G64【模板】线性基 贪心法 P3812 最大异或和

视频链接: P3812 【模板】线性基 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)// 线性基 O(63*n) #include <iostream> #include <cstring> #include <algorithm> using namespace std;typedef long long LL; int n; LL p[64];void insert(LL x){ //贪…

相机的标定

Camera-calibration 用于矫正相机的畸变代码部分 #打开摄像头,将读取的视频保存在本地,名字叫output.avi# coding=utf-8 import cv2 as cv cap = cv.VideoCapture(0) # 检查是否成功打开摄像头 if not cap.isOpened():print("Cannot open camera")exit() # 获取摄像…

关于golang函数传参问题

今天在写leetcode的一个简单问题的时候发现golang的切片传递并不是直接 传递地址的,而是一个地址副本。如图所示,当我利用test函数对nums1和nums2数组处理时,并不是对原来的nums1和nums2做处理,而是对他们的副本nums1_temp和nums2_temp做处理,但是nums1_temp和nums1都指向…

PN转Modbus RTU模块连接ACS4QQ变频器通信

巴图自动化PN转Modbus RTU模块(BT-MDPN10)的主要功能是实现Modbus协议和Profinet协议之间的转换和通信。PN转Modbus RTU模块集成了Modbus和Profinet两种协议,支持Modbus RTU主从站,可连接变频器、智能高低压电器、功率测量设备等RS485/232接口设备。一台完整的机器在出厂前由…

RS232转PN协议网关模块连接PLC和霍尼韦尔条码扫描器通信

利用RS232转PN协议网关(BT-PNR20)模块连接PLC与条码扫描器,通过配置RS232转PN协议网关(BT-PNR20)模块连接PLC与条码扫描器参数实现高效通信,提高生产效率,降低人工干预成本。涉及设备准备、硬件连接、配置步骤和监控设置。为了更快地输入信息,许多设备都配备了条码扫描…

vscode 远程连接 Ubuntu (SSH)

vscode ssh Ubuntu 流程及一些常见问题的解决安装对应的拓展包显示所有的命令(Ctrl+Shift+p)获取虚拟机的ip sudo apt install net-tools ifconfig进行连接如果连接的时候报错(管道不存在) 在Ubuntu中打开ssh服务即可如果连接了很久没有连上(Permission denied (publickey…

2024已过半,还没试过在vue3中使用ioc容器吗?

Zova 是一款支持 IOC 容器的 Vue3 框架。有了 IOC 容器的加持,定义响应式状态不再需要ref/reactive,也不再需要ref.valueVue3 已经非常强大和灵活了,为什么还要引入 IOC 容器呢?IOC 容器离不开 Class,那么我们就从 Class 谈起 Class的应用场景 一提起 Class,大家一定会想…

cpp查错误

使用Windows事件查看器调试崩溃 https://www.cnblogs.com/yilang/p/11993912.html1、2、生成.map看函数地址 3、map里找不到0xc0000409 4、 搜 异常代码 0xc0000409 5、堆栈设置

Vue3 如何接入 i18n 实现国际化多语言

如何在现有 Vue 3.0 + Vite 项目中,引入 i18n 实现国际化多语言,可以手动切换,SEO友好,且完整可用的解决方案。1. 基本方法 在 Vue.js 3 中实现网页的国际化多语言,最常用的包是 vue-i18n,通常我们会与 vue-i18n-routing 一起使用。 vue-i18n 负责根据当前页面的语言渲染…

【安全运营】企业钓鱼演练实践

一、 群智集锦 问:请教各位师傅个问题,你们多长时间做一次钓鱼演练?答:全员型的半年一次,小范围的一个季度一次;答:我们内部每月都有做钓鱼演练,主要针对新员工,钓鱼主题一般不改变,针对全员的时候会换一下套路;问:请教个问题,大家进行钓鱼演练统计是怎么统计展示…

植物大战僵尸 杂交版

下载地址:https://download.csdn.net/download/hello_hlqk/89525708?spm=1001.2101.3001.9500 植物大战僵尸杂交版是一款由B站UP主 @潜艇伟伟迷 基于原版植物大战僵尸魔改的塔防类游戏。这款游戏在保留原有游戏精髓的基础上,进行了大胆的创新和尝试。UP主将不同的植物进行了…