《剑指Offer》 递归总结篇

本文总结了《剑指Offer》中利用递归处理链表问题的方法,包括从尾到头返回链表值的ArrayList、反转链表以及合并两个单调递增链表。递归思想在解决链表问题时能简化代码,降低错误概率,但也需要注意栈溢出风险。

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

 

  • 反向遍历链表
  • 翻转链表
  • 合并两个排序的链表

0、基础

基本思想,是把规模较大的一个问题,分解成规模较小的多个子问题去解决,而每一个子问题又可以继续拆分成多个更小的子问题。

最重要的一点就是假设子问题已经解决了,现在要基于已经解决的子问题来解决当前问题;或者说,必须先解决子问题,再基于子问题来解决当前问题

【A】----依赖---->【B】----依赖---->【C】

我们的终极目的是要解决问题A,那么三个问题的处理顺序如下:

开始处理问题A;

由于A依赖B,因此开始处理问题B;

由于B依赖C,开始处理问题C;

结束处理问题C;结束处理问题B;结束处理问题A

总结:栈的核心思想是递归,递归过程返回的顺序是前进顺序的逆序。

一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

递归多用 if,选择结构。每次都要判断,层层递进,每次都调用这个函数。看起来清晰但消耗空间大

事实上,链表非常适合递归,因为我们在使用链表的时候都是使用指针,而不像数组那样直接使用一个内存块,因为递归的风险,也就是栈溢出可以避免,并且因为链表涉及到大量的指针操作,使用递归可以让我们的代码更加简洁,而且简洁的代码更不容易犯错,毕竟代码量越大,可能犯错的概率也就越大,尤其是操作指针。

int Fun(int n)
{
  if(n==1)
  {
   return 1;
  }
 else
 {
  return n+Fun(n-1);
 }
}

迭代用while ,循环结构。消耗空间小。

int sum=0,i=1;
while(i<=n)
{
sum+=i;
i++;
}

1、输入一个链表,按链表值从尾到头的顺序返回一个ArrayList 

    vector<int> printListFromTailToHead(ListNode* head) {//输入是个指针(地址),返回一个容器vector
        ListNode* p=head;
        vector<int> vec;
        if(p!=NULL)//第一步判断当下指针是否为空
        {
            if(p->next!=NULL)//第二步的下一步指向的指针不是空才能使用递归
            {
                vec=printListFromTailToHead(p->next);//递归要符合函数定义:有返回容器类型
            }
            vec.push_back(p->val);//前序遍历的判断,从最后向前执行
        }
        return vec;//满足函数定义返回类型
    }

2、输入一个链表,反转链表后,输出新链表的表头。

    ListNode* ReverseList(ListNode* pHead) {
        ListNode* p=pHead;
        //如果链表为空或者链表中只有一个元素
        if(p==NULL||p->next==NULL) 
            return p;
         else{
        //先反转后面的链表,走到链表的末端结点
        ListNode* pReverseNode=ReverseList(p->next);
         
        //再将当前节点设置为后面节点的后续节点
        p->next->next=p;
        p->next=NULL;
       // 新表头永远指向原链表的表尾     
       return pReverseNode;
         }
    }

3、输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

 法一:递归

class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        //如果其中一个是空链表,返回另外一个链表的头指针
        if(pHead1==NULL)
        {
            return pHead2;
        }
        else if(pHead2==NULL)
        {
            return pHead1;
        }
        ListNode* result=NULL;
        if(pHead1->val<pHead2->val)//这里用if还是while???递归应该是一次性的if,pHead1与pHead2
        {
            result=pHead1;
            result->next=Merge(pHead1->next,pHead2);
        }
        else
        {
            result=pHead2;
            result->next=Merge(pHead1,pHead2->next);
        }
        return result;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值