代码随想录 Day7 链表 | LC206 反转链表

四、反转链表

题目:

力扣206:反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例1:

示例2:

示例3:

输入:head = []

输出:[]

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

进阶:

链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?

解题思路分析


双指针解法:

定义两个指针curpre,用来遍历链表并进行翻转

  • cur指针指向head
  • pre指针指向cur的前一个位置,这样方便进行翻转,将cur节点指向它的前一个节点(更改指针方向);那么它的初始值就为null(因为head前面没有节点了,所以是null)

还需要一个临时指针temp来保存cur下一个节点的位置,因为cur指针指向前一个节点pre以后,它的下一个节点已经没有被其他节点所指向了,失去了链接就找不到下一个节点及其后面节点的位置了;

初始时,cur指向head,pre,指向空;然后进入循环进行第一次翻转,翻转后将指针向后移动一位:

然后依次进行翻转:

最后循环结束时,pre就指向了翻转后的新链表的头节点。

伪代码讲解:

//指针初始化,为了能翻转,让cur直接指向它的前一位

cur = head;

pre = null;

//两个指针同时向后遍历,当cur指向null的时候,pre指向原链表最后一个节点,此时结束循环,不需要再将curnull指向pre了,所以循环的结束条件是:cur=null

while(cur != null) {

        //定义一个临时指针,用来保存cur下一个节点的位置

        temp = cur.next;

        //cur节点的next指向pre

        cur.next = pre;

        //两个指针都向后移动一位

        //先移动pre;如果先移动cur,那么cur的值就已经改了,pre就无法移动到原来cur的位置了

        pre = cur;

        cur = temp;

}

//返回新链表的头节点;遍历结束时,pre指向新链表的头节点,cur指向null

return pre;

复杂度分析:

  • 时间复杂度:O(n),其中 n 是链表的长度。需要遍历链表一次。
  • 空间复杂度:O(1)。

递归解法:

按照双指针的思路来写递归的代码:

伪代码讲解:

//翻转节点指针方向的方法 reverse

reverse(cur, pre) {

        //循环结束条件cur=null ,然后直接返回新链表头指针pre

        if(cur == null) return pre;

        //这里是方法开始执行时,需要先定义一个临时指针,用来保存cur下一个节点的位置

        temp = cur.next;

        //然后进行翻转,将cur节点的next指向pre

        cur.next = pre;

        //这里要进行移动,开始下一次翻转,直接使用递归的方法

        //那么这里就需要pre = cur; cur = temp;,也就是将cur值赋给pre,temp的值赋给cur,对应到reverse(cur, pre)方法中,传入的参数就应该是(temp, cur)

        return reverse(temp, cur);

}

 

//翻转链表,参数head是要进行翻转操作的链表头指针;最后结果返回新链表的头指针

reverseList(head) {

        //这里传入上面方法中的指针curpre的初始值,分别是headnull

        //同时,这里直接返回,因为这个方法递归结束以后会返回新链表的头指针pre

        return reverse(head, null);

}

复杂度分析:

  • 时间复杂度: O(n), 要递归处理链表的每个节点
  • 空间复杂度: O(n), 递归调用了 n 层栈空间

总结:


要熟练掌握双指针的思路;递归的思路按照双指针思路来写就会非常的清晰,每个参数的赋值也不会混淆。

 

题解:


自己的解题思路:

先让p和q都指向head,然后将head指向最后一个节点(也就是直接指向翻转后的链表头节点);

p用来遍历原链表,q用来翻转未翻转部分的最后一个节点;

还是太复杂了,没想到p和q可以一起同时向后移动。

而且思路有点绕来绕去,不够简洁。

 

双指针法:

 

递归法:

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值