递归-24.两两交换链表中的节点-力扣(LeetCode)

个人主页1白天的黑夜1-CSDN博客

专栏:力扣刷题录_1白天的黑夜1的博客-CSDN博客企鹅程序员:Linux 系统与网络编程_1白天的黑夜1的博客-CSDN博客

目录

一、题目解析

[1、链表中节点的数目在范围 [0, 100] 内](#1、链表中节点的数目在范围 [0, 100] 内)

[2、0 <= Node.val <= 100](#2、0 <= Node.val <= 100)

3、只能进行节点的交换,不能修改节点内部的值

二、算法原理

解法:递归

以宏观视角待递归

通过上面的图片,我们可以知道需要经过三个阶段

1、将前两个节点后的链表通过递归函数进行两两交换,并返回头指针

2、保存第二个节点的指针,用于做新的头指针

3、将前两个节点交换,最后链接上递归函数的头指针,返回新的头指针

如何编写递归代码?

1、重复的子问题->函数头

2、只关心某一个子问题做什么->函数体

3、递归函数的出口

结合视角、如何写递归代码和自己的思路,可以先自己尝试一下编写代码,提升自己的代码能力,题目链接如下

三、代码示例

四、递归展开图

看到最后,如果对您有所帮助,还请点赞、收藏和关注一键三连,在未来还会继续带来优秀的内容,感谢观看,我们下期再见!


一、题目解析

1、链表中节点的数目在范围 [0, 100]

2、0 <= Node.val <= 100

3、只能进行节点的交换,不能修改节点内部的值

二、算法原理

本题也有迭代(循环)的解法,本篇博客会着重讲递归的思路与代码,话不多说开始进入正题。

解法:递归

以宏观视角待递归

该题的思路和206. 反转链表 - 力扣(LeetCode)类似,只不过一个是将所有反转,一个是两个两个的反转。先将前两个节点后的链表进行两两反转,然后返回一个头指针。此时通过一个ListNode*类型的变量newhead保存第二个节点,然后将第二个节点的next指向第一个节点,第一个节点的next指向递归函数返回的头指针。

通过上面的图片,我们可以知道需要经过三个阶段

1、将前两个节点后的链表通过递归函数进行两两交换,并返回头指针
2、保存第二个节点的指针,用于做新的头指针
3、将前两个节点交换,最后链接上递归函数的头指针,返回新的头指针

如何编写递归代码?

1、重复的子问题->函数头

我们的重复子问题就是将链表两两交换,需要一个ListNode*的参数,由于需要返回新的头指针,所以返回值类型是ListNode*。所以题目提供的函数可以拿过来用。

2、只关心某一个子问题做什么->函数体

我们需要一个ListNode*型的变量tmp接受递归函数的返回值,还需要一个ListNode*型的变量newhead记录第二个节点的地址也就是head->next,然后将它们三个链接起来,返回newhead这个新的头指针

3、递归函数的出口

如果一个递归函数没有一个出口(返回值),会使递归层数过多导致栈溢出。当节点为空时,直接返回nullptr;如果节点的next为空,则直接返回节点本身。

结合视角、如何写递归代码和自己的思路,可以先自己尝试一下编写代码,提升自己的代码能力,题目链接如下

24. 两两交换链表中的节点 - 力扣(LeetCode)

三、代码示例

这是递归版的代码,可以和下面迭代版的代码做一下比较

cpp 复制代码
class Solution {
public:
    ListNode* swapPairs(ListNode* head)
    {
        if(head == nullptr) return nullptr;
        if(head->next == nullptr) return head;
        ListNode* tmp = nullptr;
        tmp = swapPairs(head->next->next);
        ListNode* newhead = head->next;//保存新的头指针
        newhead->next = head;
        head->next = tmp;
        return newhead;
    }
};

迭代版的代码

cpp 复制代码
class Solution {
public:
    ListNode* swapPairs(ListNode* head)
    {
        if(head == nullptr || head->next == nullptr) return head;//0or1个节点
        ListNode* newhead = new ListNode();
        ListNode* tail = newhead;
        ListNode* cur1 = head;
        ListNode* cur2 = head->next;
        ListNode* nnext = cur2->next;
        while(cur1!=nullptr && cur2!=nullptr)
        {
            tail->next = cur2;
            cur2->next = cur1;
            cur1->next = nnext;
            tail = cur1;
            cur1=cur1->next;
            if(cur1 == nullptr) break;
            else cur2 = cur1->next;
            if(cur2 != nullptr) 
                nnext = cur2->next;
        }
        return newhead->next;    
    }
};

可以看的出来递归版的代码量明显变少了,而且少命名了一些变量,节约了空间

四、递归展开图

我们画递归展开图的目的是为了去体会函数执行和调用的过程,所以样例可以不用很复杂。这张递归展开图使用题目给的示例1 1->2->3->4->nullptr

关键点为需要保存第二个节点的地址,不然在更改指针指向时,会丢失节点的地址,导致链接出错;以及函数出口的判断传入的是head->next->next,避免出现对空指针进行访问操作

看到最后,如果对您有所帮助,还请点赞、收藏和关注一键三连,在未来还会继续带来优秀的内容,感谢观看,我们下期再见!

相关推荐
猷咪6 分钟前
C++基础
开发语言·c++
CSDN_RTKLIB13 分钟前
WideCharToMultiByte与T2A
c++
飞机和胖和黄26 分钟前
考研之王道C语言第三周
c语言·数据结构·考研
星火开发设计27 分钟前
类型别名 typedef:让复杂类型更简洁
开发语言·c++·学习·算法·函数·知识
蒹葭玉树38 分钟前
【C++上岸】C++常见面试题目--操作系统篇(第二十八期)
linux·c++·面试
醉颜凉38 分钟前
【LeetCode】打家劫舍III
c语言·算法·leetcode·树 深度优先搜索·动态规划 二叉树
达文汐41 分钟前
【困难】力扣算法题解析LeetCode332:重新安排行程
java·数据结构·经验分享·算法·leetcode·力扣
一匹电信狗41 分钟前
【LeetCode_21】合并两个有序链表
c语言·开发语言·数据结构·c++·算法·leetcode·stl
User_芊芊君子41 分钟前
【LeetCode经典题解】搞定二叉树最近公共祖先:递归法+栈存路径法,附代码实现
算法·leetcode·职场和发展
培风图南以星河揽胜42 分钟前
Java版LeetCode热题100之零钱兑换:动态规划经典问题深度解析
java·leetcode·动态规划