难度:简单
题目描述:
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
提示:
- 链表中节点的数目范围是 [0, 5000]
- -5000 <= Node.val <= 5000
警告:再往下翻就是答案了
解法1:双指针,迭代实现
- 定义两个指针: prepre 和 curcur ;prepre 在前 curcur 在后。
- 每次让 prepre 的 nextnext 指向 curcur ,实现一次局部反转
- 局部反转完成之后,prepre 和 curcur 同时往前移动一个位置
- 循环上述过程,直至 prepre 到达链表尾部
//双指针迭代实现
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null;//前指针初始指向头结点的前一个空结点
ListNode curr=head;//后指针初始指向头结点
ListNode next;//定义一个变量来临时存放二三节点的指向,以找到后一个结点位置
while(curr!=null){
next = curr.next;
curr.next = pre;
pre = curr;
curr = next;
}
return pre;//因为后指针移动到了末尾,但链表反转了,故此处才是头。
}
}
解法2:递归实现
- 使用递归函数,一直递归到链表的最后一个结点,该结点就是反转后的头结点,记作 retret
- 此后,每次函数在返回的过程中,让当前结点的下一个结点的 next.next 指针指向当前节点。
- 同时让当前结点的 nextnext 指针指向 NULL ,从而实现从链表尾部开始的局部反转
- 当递归函数全部出栈后,链表反转完成。
// 递归实现
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null)//递归开始前先判断传入的是否为空链表及是否遍历到尾部
return head;
ListNode retret = reverseList(head.next);//开始递归,传入head.next保证获得下一个结点
head.next.next = head;//这两步是将两个结点间的指向反转
head.next = null;
return retret;
}
}
碎碎念时间:
解法1注意要找个变量来存第三个结点的位置,不然反转12结点之后就没办法找到下一个结点
解法2也是没法解决找下一个结点的问题,所以干脆从尾部遍历,这样前面的指向还没有被破坏。
多画图,画个图比看字容易理解。