链表中的递归算法C语言带你看看

文章介绍了如何使用递归方法来翻转链表,包括按K个节点一组进行翻转和整体翻转链表的算法。在K个一组翻转中,递归处理k个节点,然后连接反转后的子链表;在整体翻转中,递归至链表末尾,再回溯时进行节点反转链接。这两种方法都利用了O(1)额外空间的递归策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

25. K 个一组翻转链表

难度困难1998收藏分享切换为英文接收动态反馈

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

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

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

示例 1:

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

示例 2:

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

提示:

  • 链表中的节点数目为 n
  • 1 <= k <= n <= 5000
  • 0 <= Node.val <= 1000

进阶:你可以设计一个只用 O(1) 额外内存空间的算法解决此问题吗?

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* reverseKGroup(struct ListNode* head, int k)
{
    //创建是那个指针 s记录反转之后的头节点 e记录反转之后的尾节点 c要反转的下一个节点
    struct ListNode* ptrStart;
    struct ListNode* ptrEnd;
    struct ListNode* ptrCurr;
    if(head == NULL)
    {
        return head;
    }
    //如果头节点不为空 但所有节点之和不等于k也就不反转 直接返回head
    ptrCurr = head;
    for(int i = 0;i<k;i++)
    {
        if(ptrCurr != NULL)
        {
            ptrCurr = ptrCurr->next;
        }
        else{
            return head;//遇到空就返回头节点
        }
    }
    //将k个元素反转 首先要明白 两个元素进行翻转需要进行1此 以此类推 k个元素 需要k-1次
    ptrStart = head;
    ptrEnd = ptrStart;
    ptrCurr = ptrStart->next;
    for(int i = 1;i<k;i++)
    {
        if(ptrCurr)
        {
            ptrEnd->next = ptrCurr->next;
            ptrCurr->next = ptrStart;
            ptrStart = ptrCurr;
            ptrCurr = ptrEnd->next;
        }
    }
    ptrEnd->next = reverseKGroup(ptrCurr,k);//递归 看起来还是挺简洁的
    return ptrStart;
}

思路理解

 

对于这个递归 他向下归的时候 就对k个节点进行了翻转  达到递归条件返回时 只返回了头节点 也就是S 或者head 将返回的节点连接到E->next 就达到了k个节点的翻转

206. 反转链表

难度简单3107收藏分享切换为英文接收动态反馈

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

示例 1:

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

示例 2:

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

示例 3:

输入:head = []
输出:[]

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000
struct ListNode* reverseList(struct ListNode* head) {
    if (head == NULL || head->next == NULL) {
        return head;
    }
    struct ListNode* newHead = reverseList(head->next);
    head->next->next = head;
    head->next = NULL;
    return newHead;
}

这个递归就是先归到链表末尾 将最后一个节点作为头节点 newhead (记录翻转后的头节点)上一层函数调用中的head 是指向倒数第二个节点的 所以head->next->next 就是最后一个节点中存放下一个节点的指针 让倒数第一个节点指向倒数第二个节点 再将倒数第二个节点指向空 达到了一次翻转 

递归调用个人感觉就像是用调用自身的那部分将整个函数划分两部分 

第一部分 :就是向下递归时要做什么

第二部分 :就是向上递归时要做什么

再来个递归条件 什么时候停止 我感觉还是 考虑好第一部分 和 第二部分 在这个过程中你肯定会考虑到递归条件是什么

确实不太好想 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

挣扎的泽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值