「这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战」
刷了400多题,做了七八遍反转链表,几个月之后再做两种方法还是都不会做,我是废物 ;(
——leetcode此题热评
前言
大家好,我是一条,欢迎来到我的算法频道。
只做有趣的算法题,只为面试写算法。
Question
206. 反转链表
难度:简单
Solution
这道题刷过一遍,就像评论说的,还是记不住,再战翻转链表。
迭代法
在遍历链表时,将当前节点的 \textit{next}next 指针改为指向前一个节点。由于节点没有引用其前一个节点,因此必须事先存储其前一个节点。在更改引用之前,还需要存储后一个节点。最后返回新的头引用。
递归法
递归版本稍微复杂一些,其关键在于反向工作。假设链表的其余部分已经被反转,现在应该如何反转它前面的部分?
- 使用递归函数,一直递归到链表的最后一个结点,该结点就是反转后的头结点,记作 retret
- 此后,每次函数在返回的过程中,让当前结点的下一个结点的 nextnext 指针指向当前节点。
- 同时让当前结点的 nextnext 指针指向 NULLNULL ,从而实现从链表尾部开始的局部反转
- 当递归函数全部出栈后,链表反转完成。
Code
/**
* @author 一条coding
* public class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}
*/
class Solution {
public ListNode reverseList(ListNode head) {
// 迭代
// 当前只指针的next指向前一个指针 同时记录当前节点的前一个和后一个。
ListNode prev=null;
ListNode cur=head;
// 遍历
while (cur!=null){
// 记录下一个节点作为下一次循环
ListNode next=cur.next;
// 核心
cur.next=prev;
// 交换后当前节点变为下一次循环的饿前一个节点
prev=cur;
// 下一次循环
cur=next;
}
// 返回 cur=null
return prev;
}
}
递归
class Solution {
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
}
最后
最后,如果文章对你有帮助。
记得给文章点个赞呀!
也给 一条点个关注!