剑指offer24——双指针&&递归法解决链表翻转(带图讲解)

在学完链表的基础操作——增删查改之后,今天我们来讲解一道非常经典的链表题,链表的翻转。

 

                                               双指针迭代

思路:

我们知道单链表顾名思义是单向的,也就是只能按照从前往后的顺序进行访问,所以如果想要进行翻转,肯定是需要两个指针的,也就要运用双指针法

我们用prev和cur表示前后指针,注意这里要养成良好的命名习惯,让别的人看代码比较容易清楚逻辑,而不是命名为a,b,那就让人看着很头疼,不知道什么意思。

接下来我们来画图进行模拟一下。这是单链表开始的模样

我们先完成双指针的赋值。cur指向头结点head。当整个链表都翻转完后 ,此时的头结点就应为尾结点了,尾结点的next又应该指向NULL,所以我们翻转头结点时,将prev赋值为NULL——prev=NULL,cur=head,cur->next=prev,这样就完成第一个头结点的翻转了

 当我们完成这一步后,我们就会发现我们访问不了第二个结点了,因为头结点的next已经被修改了,这里也没有其他办法可以挽救了。

既然修改next后就无法访问下一个结点,那我们也不要吝啬一点空间,在翻转前先定义一个指针struct ListNode*tmp保存cur的下一个结点的位置,然后再进行cur->next(箭头)的修改,接着让prev来到cur的位置,cur来到tmp的位置,这样就完成一次翻转了。

我们也发现这里需要很多个tmp,所以tmp变量应该是循环体里定义声明的,这样就方便很多。

我们来画图展示一下

 

 

 这样子不断的循环,直到cur指向cur,循环结束,此时prev指向开始的尾结点,也就是反转后的头结点,所以我们返回prev指针就好了,总体思路如上。

思路明确,我们写起来也就水到渠成了。代码如下

struct ListNode* reverseList(struct ListNode* head){
    if(head==NULL)//如果链表为空,直接返回NULL
    return NULL;

    struct ListNode*prev,*cur;//对双指针进行赋值
    prev=NULL,cur=head;

    while(cur)//当cur不为空时,继续翻转操作
    {
        struct ListNode*tmp=cur->next;//先保存下一个头结点地址,以防修改完箭头找不到
        //双指针进行翻转操作
        cur->next=prev;
        prev=cur;
        cur=tmp;
    }
    return prev;//返回原本的尾结点,现在的头结点。
}

在学习完双指针翻转链表的过程后,不难发现这是一个重复一个动作的过程,那应该就可以有递归写法。

递归的代码会比循环看起来更加简洁,但是当数据过多时可能会栈溢出,所以我们要正确看待迭代和递归两种解决方案,不要盲目地认为递归就是比迭代好,这是不正确的。

                                                      递归

在敲递归的代码之前,我们会发现好像很难下手。所以我们仿照双指针的思路来写递归的代码。

思路:

我们需要一个reverse(prev,next)函数来进行翻转

第一次翻转头结点时需要将头结点指向NULL,所以我们传head和NULL进reverse函数

我们知道递归时cur会一步一步往后走,不断进入reverse函数。所以cur指向NULL时,翻转也就结束了,返回prev

接下来就是翻转链表,我们还是需要tmp来存储cur的下一个地址,然后改变箭头,这里和之前没有差别,接下来就是关键了——prev=cur;cur=tmp两步就是指针移动,我们应该在这里进入递归,调用reverse函数。

关于形参我们就按照 prev=cur;cur=tmp照抄就好,这里将cur赋值给了prev,tmp赋值给了cur

所以reverse(cur,tmp)

至此递归的写法就完成啦!这样想是不是思路一下子就明朗了,原本很难得的写法其实也就是照葫芦画瓢罢了,不过前提是我们要对双指针熟练掌握!

代码如下:

struct ListNode*reverse(struct ListNode*cur,struct ListNode*prev)
{
    if(cur==NULL)
    return prev;
    
    struct ListNode*tmp=cur->next;
    cur->next=prev;
    reverse(tmp,cur );
}
struct ListNode* reverseList(struct ListNode* head){
    return reverse(head,NULL);
}

本题的讲解就结束啦,希望大家多多点赞关注,支持一下!我也会继续输出编程知识的

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值