024.两两交换链表中的节点,用递归和 while 循环

题意

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

难度

中等

示例

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

分析 1

看到这道题,我们要先搞清楚什么是两两交换,比如 1->2->3->4,交换后就是 2->1->4->3。

第一个和第二个交换,第三个和第四个交换,以此类推。

我们可以用递归来解决这个问题,递归的终止条件是当前节点或者下一个节点为空,那么递归的返回值就是当前节点。

比如说 1 和 2 交换后, 2 的 next 指向 1,1 的 next 指向下一次交换后的结果。

我们来看题解的代码:

class Solution {public ListNode swapPairs(ListNode head) {// 递归终止条件:链表没有节点或只有一个节点if (head == null || head.next == null) {return head;}// 准备交换ListNode firstNode = head;ListNode secondNode = head.next;// 递归处理剩下的节点firstNode.next = swapPairs(secondNode.next);// 交换secondNode.next = firstNode;// 返回交换后新的头节点return secondNode;}
}

本地测试


/*** @ClAssName SwapPairs* @Description 两两交换链表中的节点,用递归和 while 循环轻松解决* @Author 欧妮甲是神仙* @Date 2024/6/24 19:{MINUTE}*/
public class SwapPairs {public static void main(String[] args) {SwapPairs swapPairs = new SwapPairs();ListNode head = swapPairs.new ListNode(1);head.next  = swapPairs.new ListNode(2);head.next.next  = swapPairs.new ListNode(3);head.next.next.next  = swapPairs.new ListNode(4);ListNode result = swapPairs.swapPairs(head);while (result !=null){System.out.println(result.val + " ");result = result.next;}}class ListNode{int val;  //数据ListNode next;  //指针ListNode(){};  //空参构造ListNode(int val){  //数据对象this.val = val;}//完整的对象ListNode(int val , ListNode next){this.val=val;this.next = next;}}public  ListNode swapPairs(ListNode head){//1、递归终止条件:链表没有节点或只有一个节点if (head == null || head.next ==null){return head;}//2、准备交换//第一个节点ListNode firstNode = head;//第二个节点ListNode secondeNode = firstNode.next;//3、递归·处理后续节点  重点  =后面的处理后续节点的,比如3和4的   =前面是连接后续的节点的firstNode.next = swapPairs(secondeNode.next);//4、交换secondeNode.next = firstNode;//5、返回交换完后新的头节点return secondeNode;}}

我们从链表的头节点 head 开始递归,每次处理一对节点,交换这对节点后,递归处理剩下的节点。

如果链表没有节点或者只有一个节点,没有交换的需要,直接返回 head。看下面这幅图就明白了。

来看题解效率:

分析 2

如果不想使用递归的话,我们也可以使用一个 while 循环来解决。

第一步,我们创建一个虚拟节点作为新链表的头节点,这可以简化边界条件的处理,虚拟节点的下一个节点指向 head。

第二步,我们开始 while 循环,条件是 head 和 head.next 都不为空。

第三步,我们使用两个临时变量来保存 head 和 head.next,然后交换这两个节点。

第四步,记得更新指针。

第五步,返回虚拟节点的下一个节点。

我们来看下面的代码:

class Solution {public ListNode swapPairs(ListNode head) {// 创建哑节点ListNode dummy = new ListNode(-1);dummy.next = head;ListNode prev = dummy;while (prev.next != null && prev.next.next != null) {ListNode curr = prev.next; // 当前节点ListNode next = curr.next; // 下一个节点// 交换 curr 和 nextcurr.next = next.next;next.next = curr;prev.next = next;// 移动指针prev = curr;}return dummy.next;}
}

简单解释下:

  • 创建一个虚拟节点 dummy,dummy 的 next 指向 head。
  • 创建一个指针 prev,指向 dummy。
  • 当 prev 的 next 和 next 的 next 都不为空时,进行交换。
  • 交换后,prev 指向 curr,curr 指向 next,next 指向 curr 的 next。
  • 返回 dummy 的 next。

因为增加了很多临时变量,所以代码没有递归简洁。

    public  ListNode swapPairsTwo(ListNode head){//1、创建一个虚拟的节点作为新链表的头节点,简化边界条件的处理,其下一个节点指向headListNode dummy = new ListNode(-1);dummy.next = head;ListNode prev = dummy;//2、我们while循环 ,条件是head和head.next都不为空while (prev.next != null &&prev.next.next != null){//3、使用两个临时变量来保存head和head.next,然后交换这两个节点ListNode curr = prev.next;  //当前节点ListNode next = prev.next.next;  // 下一个节点//4、交换curr和nextcurr.next = next.next;next.next = curr;prev.next = next;//5、移动指针prev = curr;}//最后返回头节点return dummy.next;}

来看题解效率:

总结

其实有关链表的相关题目,最重要的切入角度,就是理清楚节点之间的关系,然后在纸上画一画,不要一个劲的只靠脑子不靠笔,往往思考了很久的问题,动动笔,就会豁然开朗,再用代码准确的描述出思路,这样子链表的问题便迎刃而解。

那这道题考察的还是链表的数据结构,以及递归和 while 循环的一些临时变量和边界条件。

力扣链接:. - 力扣(LeetCode)

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

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

相关文章

什么是车载测试?车载测试怎么学!

1、车载测试是什么? 车载测试分很多种,有软件测试、硬件测试、性能测试、功能测试等等,每一项测试的内容都不一样,我们所说的车载测试主要指的是汽车软件的功能测试,也就是针对汽车实现的某一个功能,而进行…

vue3 vxe-grid列中绑定vxe-switch实现数据更新

1、先上一张图&#xff1a; <template #valueSlot"{ row }"><vxe-switch :value"getV(row.svalue)" change"changeSwitch(row)" /></template>function getV(value){return value 1;};function changeSwitch(row) {console.l…

Trilium windows上修改笔记目录,创建多个笔记空间方法

一开始使用trilium会非常的不舒服&#xff0c;不像是obsidian可以创建多个笔记空间&#xff0c;指定多个笔记目录。这里摸索到了解决方案 修改目录的方法一 ——修改系统环境变量 打开控制面板-系统-高级系统设置 新增如上条目 修改目录的方法二——直接写bat脚本运行 新建位…

深入理解Kubernetes:CNI源码解析

在容器化环境中&#xff0c;有效管理网络是至关重要的。容器网络接口&#xff08;CNI&#xff09;是一个标准&#xff0c;定义了容器应如何配置网络。本文将深入探讨 CNI 的基础知识&#xff0c;并带你了解 CNI 与 CRI 的关系。 什么是 CNI&#xff1f; CNI&#xff08;容器网…

Redis哨兵集群搭建

一、安装Redis 1.安装依赖 yum install -y gcc tcl2.将Redis压缩包解压到对应的目录 tar -zxvf redis-2.8.0.tar.gz mv redis-2.8.0 /usr/local3.编译 cd /usr/local/redis-2.8.0 make && make install4.配置redis.conf # 任意ip都可以访问 bind 0.0.0.0 # 关闭保…

网安大咖说·镜鉴(下)| 把握安全新脉搏:企业CSO的领航之道

网安大咖说镜鉴栏目通过对网安大咖说嘉宾访谈内容的深度提炼&#xff0c;撷取群英论道之精髓&#xff0c;汇聚众智谋策之高远&#xff0c;为从业者提供宝贵的经验和启迪。集思广益、博采众长&#xff0c;意在以镜为鉴&#xff0c;观网安之百态&#xff0c;立防范之策略&#xf…

Linux 内核缓存一致性相关机制和接口梳理

From 程序员秘书 缓存一致性是一个非常关键的问题&#xff0c;特别是在多核处理器和直接内存访问&#xff08;DMA&#xff09;场景下。原因如下&#xff1a; 多核CPU与cache的缓存一致性问题&#xff1a;每个CPU core都有自己的cache&#xff0c;由于cache的写回机制&#xf…

AI助力科研:自动化科学构思生成系统初探

科学研究作为推动创新和知识进步的关键活动&#xff0c;在解决复杂问题和提升人类生活水平方面发挥着至关重要的作用。然而&#xff0c;科学研究的固有复杂性、缓慢的进展速度以及对专业专家的需求&#xff0c;限制了其生产力的提升。为了增强科研效率&#xff0c;本文提出了一…

力扣78 子集

给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的 子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[],[1],[2],[1,2],[3],…

Linux使用pthread多线程时cmake新增语句

https://cmake.org/cmake/help/latest/module/FindThreads.html 在子文件夹中的CMakeList.txt&#xff1a; aux_source_directory(. DIR_SUB_SRCS) add_library(echatlib SHARED ${DIR_SUB_SRCS}) # STATIC SHARED# 方法一 find_package(Threads REQUIRED) target_link_librar…

鸿蒙开发Ability Kit(程序框架服务):【FA模型绑定Stage模型ServiceExtensionAbility】

FA模型绑定Stage模型ServiceExtensionAbility 本文介绍FA模型的三种应用组件如何绑定Stage模型的ServiceExtensionAbility组件。 PageAbility关联访问ServiceExtensionAbility PageAbility关联访问ServiceExtensionAbility和PageAbility关联访问ServiceAbility的方式完全相同…

重学java 84.Java枚举

那些你暗自努力的时光&#xff0c;终究会照亮你前行的路 —— 24.6.24 一、枚举介绍&#xff08;开发中表示状态&#xff09; 1.概述&#xff1a; 五大引用数据类型&#xff1a;类型、数组、接口、注解、枚举 2.定义&#xff1a; public enum 枚举类名{} 所有的枚举类父类…

集成Stata分布式事务

一.事务协调器TC 1&#xff0e;安装Seata-server 下载&#xff1a;https://github.com/seata/seata/tags 启动&#xff1a;seata-server.bat -p 8091 -h 127.0.0.1 -m file 关闭其他服务&#xff0c;先启动它 2&#xff0e;配置文件修改 二.主业务端TM 1&#xff0e;导入依赖…

贝锐花生壳内网穿透

贝锐花生壳内网穿透使用步骤 首先你得去官网购买一个域名配置一下内网穿透映射官网下载一个客户端修改代码配置 首先你得去官网购买一个域名 配置一下内网穿透映射 官网下载一个客户端 注意&#xff0c;一定要下载客户端&#xff0c;不然用不了 当然&#xff0c;本地我已经提前…

SpringBoot-配置文件中使用随机值和使用变量

1、配置文件中使用随机值 2.在配置文件使用引用变量 如果没定义还可以设置默认值

NIO(三) Selector使用(NIO综合)

Selector&#xff08;选择器&#xff09;能够管理一到多个Channel&#xff08;通道&#xff09;&#xff0c;监听通道是否为事件做好准备。 一&#xff0c;使用Selector的好处 只需少量线程来处理多个通道&#xff0c; 从而管理多个网络连接。 二&#xff0c;Selector示例 服务…

环境安装-GIT

下载 git官网下载 https://git-scm.com/ 安装 点击下载的安装包&#xff0c;并点击下一步 选择安装路径&#xff0c;照例改选自定义路径 选择默认的即可 选择GIT编辑器&#xff0c;默认选择vim即可 设置初始化新项目(本地仓库)的主分支名&#xff0c;按默认即可&#xff0c;点…

keysight 34901A (安捷伦)多路复用器

34970A 数据采集/开关单元的 Keysight 34901A&#xff08;安捷伦&#xff09;模块是通用扫描中最通用的多路复用器。它将密集的多功能开关与 60 通道/秒的扫描速率相结合&#xff0c;可满足广泛的数据采集应用。两线和四线通道可以混合在同一模块上。两个额外的保险丝输入&…

Hadoop 面试题(八)

1. 在 Hadoop 集群的配置文件中有如下两个配置&#xff0c;请问假如集群中有一个节点宕机&#xff0c;主节点 namenode 需要多长时间才能感知到&#xff08;&#xff09; &#xff1f; dfs.heartbeat.interval 3heartbeat.recheck.interval 2000A&#xff1a;26秒 B&#xff1…

音频傅里叶变换(基于开源kissffs)

主要参考资料&#xff1a; 深入浅出的讲解傅里叶变换&#xff08;真正的通俗易懂&#xff09;: https://zhuanlan.zhihu.com/p/19763358 推荐开源项目&#xff1a;KISS FFT&#xff1a; https://blog.csdn.net/gitblog_00031/article/details/138840117 数字硅麦数据的处理&…