递归函数对于链表进行反转的三个题目

举报
qingchuan666 发表于 2025/07/30 22:06:21 2025/07/30
【摘要】 递归函数

1.第一题

还是老朋友,反转链表,但是这一次我们使需要使用递归来进行求解:

image-20250730195719469

下面的这个是使用递归的方法对于上面的问题进行求解的代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode listnode;
struct ListNode* reverseList(struct ListNode* head) {
    if(head==NULL||head->next==NULL){
        return head;
    }
    listnode* cur=reverseList(head->next);
    head->next->next=head;
    head->next=NULL;
    return cur;
}

1)在上面的这个代码里面,我们的cur实际上指向的就是我们的

image-20250730200642189

2)翻转链表主要还是需要修改我们的这个链表里面的next指针的指向,因此上面的这个代码里面head两次进行这个next的操作,实际上就是修改了我们的原本的指针的指向,具体的示意图我放在了下面,例如我们需要修改这个23之间的指向,这个时候的3相当于就是我们的head->next,这个时候的head->next->next就是这个3指向的就是2这个节点,因此这个就是相当于对于我们的这个链表里面的节点的指针的指向发生了翻转;

image-20250730200659837

3)head->next指向null表示的就是对于我们的这个1这个节点指向空,相当于是对于

2.反转链表II

下面的这个题目我们应该也是非常熟悉的,但是需要我们使用递归进行求解:这个题目和上面的题目的区别就是这个题目里面添加了我们的左右键的限定,相当于是在这个指定的区间里面进行这个翻转的过程;

image-20250730202239582

下面的这个是我们的代码:讲述的过程中使用示例1来进行说明哈;

1)主函数的between函数,pro函数属于是我们的自定义函数,刚开始的时候这个pre和end都是指向的我们的虚拟头结点,两个for循环找到这个区间的起始节点和最后一个节点;

2)这个pro函数的逻辑实际上就是我们的上面的第一个题目的链表翻转逻辑,相当于这个链表的头结点是begin,尾结点是end,代码和上面的是完全一样的;

3)e节点里面存放的就是反转之后的头结点,对应的代码我使用AI进行解释,我觉得很不错,大家可以结合者看一下

image-20250730215412827

image-20250730215502892

4)主函数的返回值的话,就是我们的虚拟头的下一个节点哈;

class Solution {
public:
    ListNode* reversepro(ListNode* begin , ListNode* end){
        if(begin->next == end){
            return begin;
        }
        ListNode* newhead = reversepro(begin->next , end);
        begin->next->next = begin;
        begin->next = nullptr;
        return newhead;
    }
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        if(!head || !head->next || left == right){
            return head;
        }


        ListNode* dumbnode = new ListNode(0 , head);
        ListNode* pre = dumbnode;
        ListNode* end = dumbnode;
        for(int i = 0 ; i < left-1 ; ++i){
            pre = pre->next;
        }
        for(int i = 0 ; i < right + 1 ; ++i){
            end = end->next;
        }


        ListNode* e = reversepro(pre->next , end);
        pre->next->next = end;
        pre->next = e;
        return dumbnode->next;
    }
};

3.第三个题目

下面的这个题目是几个节点一组进行这个翻转的过程:我记得这个题目,我自己第一次写的时候使用的是优先级队列进行求解的,没想到这个题目居然也可以使用递归进行求解;

image-20250730202452152

1)下面的这个也是使用的递归的方法对于问题进行求解:

findEnd函数是我们的这个自定义函数,这个函数的主要作用就是找到我们的一组链表里面的尾结点,把这个尾结点作为返回值返回即可;

2)reverse函数就是进行的这个区间交换的过程,这个就是经典的三个指针解决的问题啦;

3)在我们的这个主要的函数里面,newhead找到这个尾结点,next相当于就是记录这个一组链表的下一个基点,renverse函数对于当前的这一组进行翻转的过程;

4)接下来的这个递归函数就是对于下一组进行翻转的过程,next相当于就是我们的下一组的第一个基点,从这个节点开始的k歌元素进行这个翻转的过程;

class Solution {
public:
    ListNode* findEnd(ListNode* head,int k){
        while(--k>0 && head != nullptr){
            head = head ->next;
        }
        return head;
    }
    void reverse(ListNode* head,ListNode* end){
        ListNode* pre = nullptr;
        ListNode* cur = head;
        ListNode* next = nullptr;
        while(cur!=end){
           next = cur ->next;
           cur->next = pre;
           pre = cur;
           cur = next;    
        }
        end->next = pre;

    }
    ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode* newHead = findEnd(head,k);
        if(newHead == nullptr){
            return head;
        }
        ListNode* next = newHead->next;
        reverse(head,newHead);
        head->next = reverseKGroup(next,k);
        return newHead;

    }
};
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。