反转链表 【指针迭代法、递归实现】(leetcode-206)

关于链表的基本操作和一些LeetCode题目集合


目录

题目描述:

迭代法:

分析:

实现:

代码:

递归法:

递归结束的条件:

开始翻转:

后续翻转:

代码:


题目描述:

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

迭代法:

分析:

如果再定义一个新的链表,实现链表元素的反转,其实这是对内存空间的浪费。

其实只需要改变链表的next指针的指向,直接将链表反转 ,而不用重新定义一个新的链表,如图所示:

206_反转链表.png

之前链表的头节点是元素1, 反转之后头结点就是元素5 ,这里并没有添加或者删除节点,仅仅是改表next指针的方向。

实现:

我们都知道交换两杯水必须用第三个杯子来做中间的桥梁,反转链表也是如此。

假设对于一个节点t,我们知道了他的前驱是pre,后继可以直接用t->next访问,

翻转的话,是需要将t改为指向pre这个节点,改完后,会出现一个问题,那就是t的next丢失了,或者说我们找不到一个入口再去访问next这个后继了,因为之前的唯一访问入口是t->next,而现在t->next已经被覆盖。

           

所以为了解决这个问题,我们再引入“第三个杯子”指针temp,将在next丢失前用temp存储下来,这样当pre和t处理完成之后,再顺次处理的应该就是t和temp了,所以我们迭代用temp和t去更新t和pre。

另外,头指针的前驱应该是NULL,翻转结束后新的头指针应该是pre。

代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* pre=NULL;
        ListNode* t=head;
        while (t!=NULL){
           ListNode* temp=t->next; 
           t->next=pre;
           pre=t; 
           t=temp;
        }
        return pre;
    }
};

递归法:

递归的思路就是先递归到底, 找到最后一个节点, 然后从最后一个节点开始, 把箭头方向掉转。

image.png

递归结束的条件:

        if (head==NULL) return NULL;
        if (head->next==NULL) return head;

当输入是个空链表,直接返回NULL;

或者到了最后一个节点的时候,递归就结束了,我们的目标就是找到最后一个节点倒着翻转链表。

指针p代表着翻转之后的新链表的头指针,在找到最后一个节点的时候,p就确定了,并且不会再更改, 不断返回给上一层递归。

image.png

开始翻转:

在最底层递归,我们很明显的要做的是让p指向head,让head指向NULL,这样我们就完成了head和p这一部分的翻转。

但是这里注意,我们不能直接写head=NULL;p->next=head; 因为不具有普遍性,下一层要修改的就不是head和p了,而是head和head的后继,所以我们要用head来访问head的后继,让head的后继指向head这个操作的代码实现:

head->next->next = head;

再把head的next指向空, 作为新链表的最后一个节点

head->next = NULL;

这样就完成了这一层head和p的翻转。

后续翻转:

在之后,每次翻转的都是head和head的后继,如图:

image.png
递归结束, 最后返回的p(头节点)。

代码:

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (head==NULL) return NULL;
        if (head->next==NULL) return head;
        ListNode* p=reverseList(head->next);
        head->next->next=head;
        head->next=NULL;
        return p;
    }
};

参考LeetCode答案:https://leetcode-cn.com/problems/reverse-linked-list/solution/zhu-bu-tu-jie-di-gui-die-dai-by-sucongcjs/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值