题目:
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。要求是不能申请额外的内存空间。
示例 1:
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
思路分析:
如果定义一个新链表实现链表元素的反转,会对内存造成浪费。所以不使用这种方法,只需要改变链表next指针的指向,直接将链表进行反转就可以。
方法1:双指针法。
定义一个cur指针,指向头节点,定义一个pre指针,初始指向null,使用头插法。
我们使用temp指针来保存cur.next,也就是下一个要处理的节点,使用头插法cur.next指向pre,然后更新pre和cur指针。
代码如下:
class Solution {
public ListNode reverseList(ListNode head) {
ListNode temp;
ListNode pre = null;
ListNode cur = head;
while (cur != null) {
// 保存下一个节点,因为接下来要改变cur.next
temp = cur.next;
cur.next = pre; //头插
pre = cur; //更新pre指针
cur = temp;//更新cur指针,处理下一个节点
}
return pre;
}
}
最后,cur指针指向null,循环结束,链表反转结束,此时,pre指针指向了新的头节点,返回pre即可。
方法2:递归法。
递归方法和方法一实际上没啥区别。直接看代码吧。
class Solution {
public ListNode reverseList(ListNode head) {
return reverse(null, head);
}
public ListNode reverse(ListNode pre, ListNode cur) {
if (cur == null) {
return pre;
}
ListNode temp = cur.next;
cur.next = pre;
return reverse(cur, temp);
}
}
OK!我们来看一下,定义一个reverse函数,用来就是反转的,与方法1相比其实就是将更新pre和cur节点省去了,使用递归来完成。