LeetCode(力扣)::206.反转链表

目录

 1、题目

 2、思路

 3、实现

 4、结果与总结

-1、完整代码


1、题目

        我们通过阅读题干,可以得到的信息有:传给我们的是一个链表的头结点,需要我们将整个链表翻转(头变尾,尾变头),再将新链表的头结点返回。

2、思路

        题目告知我们,可以使用递归和迭代两种方法进行实现。为了便于理解,这里采用迭代的方法进行答题。我们对比一下翻转链表的两种方法:

        1、先遍历当前链表,再创建新链表,从原链表的尾结点开始,从后向前取出结点,再依次放入新链表中,全部完成之后,返回新链表的头结点。

        2、直接在原链表中进行翻转,只改变next指针的指向,让从前向后指,变成从后向前指。

 在时间复杂度上,两种方法没有优劣之分,但是由于第一种方法需要开辟新的空间来存放新链表,在空间复杂度上,第二种方法是可以节约空间的。所以我们认为第二种方法更好。

3、实现

    struct ListNode* prev = NULL;
    struct ListNode* cur = head;
    struct ListNode* tail;

        在函数内创建三个指针prev(前指针)、cur(当前指针)、tail(后指针)(也可以使用head指针来代替cur指针,我们这里为了方便理解,创建三个指针,以免初学者混淆概念)。

        在逻辑结构上我们想要实现的样子是:

        即prev一开始不指向任何元素,只知道他在cur指针之前,而tail永远指向cur后一个位置,在改变cur->next之后起定位作用。

        

         接下来我们就可以让三个指针依次前进,遍历整个链表,在遍历的过程当中,让cur->next从指向tail,变为指向prev。也就是从前向后指,变成从后向前指!这样我们就可以完成一次结点的翻转。

        当翻转到最后一个结点的时候,我们需要考虑一个问题。此时tail已经指向了NULL,如果再次后移,tail所指向的位置就不确定了,会变成一个野指针。而cur所指向的就会成为NULL,prev变成cur的位置,那我们应当返回的是cur还是prev呢?

        其实这两个问题都很好解释,当tail已经为NULL的时候,我们因当停止后移tail指针,以防tail指针指向不明内存空间。

    while(cur)//此时cur已经为NULL,tail指针不能再向后移
    {
        tail = cur->next;
        cur->next = prev;

        prev = cur;
        cur = tail;
    }

        再来考虑返回值的问题,我们需要返回的是新链表的头结点,那么我们三个指针当中,哪个是指向头结点的指针呢?首先排除tail,因为他最后一定是遍历到链表最后的位置,而cur此时的位置指向的是原链表的NULL位置。所以只有prev指向的是原链表的最后一个元素。经过一番简单的分析,我们可以得知,return的应该是prev指针。

4、结果与总结

        leetcode通过。

         此题不仅考验我们对于链表next指针的理解,同时也考察了我们对于代码的掌控能力。我们要时刻控制指针的指向位置,防止发生危险访问,并且要保证指针的顺序。严格按照前中后的顺序去移动。

-1、完整代码

//写法一
struct ListNode* reverseList(struct ListNode* head)
{
    struct ListNode* prev = NULL;
    struct ListNode* cur = head;
    struct ListNode* tail;

    while(cur)
    {
        tail = cur->next;
        cur->next = prev;

        prev = cur;
        cur = tail;
    }
    return prev;
}
//写法二
struct ListNode* reverseList(struct ListNode* head)
{
    if(head == NULL)//如果链表为空,则不需要翻转,返回空指针
    {
        return NULL;
    }
    struct ListNode* prev = NULL;
    struct ListNode* cur = head;
    struct ListNode* tail = cur->next;

    while(cur)//用来控制翻转次数
    {
        //变更指向
        cur->next = prev;

        //指针移动
        prev = cur;
        cur = tail;
        if(tail)
        {
            tail = cur->next;
        }
    }
    return prev;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值