持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例一
输入: head = {1,2,3,4,5}
输出: {5,4,3,2,1}
示例二
输入: head = {1,2}
输出: {2,1}
示例三
输入: head = {}
输出: {}
提示:
- 链表中节点的数目范围是
[0, 5000] -5000 <= Node.val <= 5000
解题思路: (双指针)
我们只需要通过更改节点的next指针就可以反转整个链表,这样做的好处是不需要再单独创建一个链表,存放反转后的节点,减少了内存空间上的损耗。如下图所示:
因为反转链表需要遍历整个链表,我们可以通过双指针的方式来实现链表的反转
首先我们先定义一个per指针,用来指向头节点。再定义一个cur指针,初始化为null
现在要开始反转了,现将 per.next 用 temp指针 保存下来,也就是保存住这个节点
per.next = cur,更改后,per指针指向的节点就变成了null,完成了第一个节点的反转
cur = per,完成 cur指针 的移动
per = temp,完成 per指针 的移动
接下来,就是循环走代码逻辑了,继续移动pre和cur指针
最后,per指针 已经指向了null,循环结束,链表也反转完毕了。 cur指针就指向了新的头结点,我们直接返回就行
代码: (Java实现)
/**
* Definition for singly-linked list.
* 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) {
ListNode cur = null;
ListNode per = head;
ListNode temp = null;
while (per != null) {
temp = per.next;
per.next = cur;
cur = per;
per = temp;
}
return cur;
}
}
复杂度分析
- 时间复杂度:O(n)
- 空间复杂度:O(1)
提交结果
解题思路: (递归)
递归从逻辑上来讲跟双指针一样,都是当cur为空的时候退出循环,不断的将cur指向per的过程
关键在于初始化的地方,在双指针中,cur = null,per = head都进行了初始化。其实递归也进行了初始化,只不过写法和双指针不同,看代码也能看出
代码: (Java实现)
/**
* Definition for singly-linked list.
* 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) {
return reverse(null,head);//相当于初始化了per,cur
}
public ListNode reverse(ListNode per,ListNode cur) {
if (cur == null) {
return per;
}
ListNode temp = null;
temp = cur.next;//先保存下一个节点
cur.next = per;//进行反转
per = cur;//更新cur,per的位置
cur = temp;
return reverse(per,cur);
}
}
复杂度分析
- 时间复杂度:O(n)
- 空间复杂度:O(1)