方式一:将原节点从原链表摘下,后续节点利用头插法插入新链表头,最后返回新链表头
public class Solution {
public ListNode ReverseList(ListNode head) {
ListNode newHead = null;
ListNode cur = null;
while(head!=null)
{
cur=head;
head=head.next;
cur.next=newHead;
newHead=cur;
}
return newHead;
}
}
复杂度分析
时间O(n)
空间O(n)
方式二:三指针
public class Solution {
public ListNode ReverseList(ListNode head) {
if(head==null || head.next==null)
return head;
ListNode pre=null;
ListNode cur=null;
while(head!=null)
{
cur=head;
head=head.next;
cur.next=pre;
pre=cur;
}
return pre;
}
}
复杂度分析
时间复杂度:O(n), 遍历一次链表
空间复杂度:O(1)
方式三:递归
代码实现:
public 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;
}
}
复杂度分析
时间复杂度:O(n),其中 n 是链表的长度。需要对链表的每个节点进行反转操作。
空间复杂度:O(n),其中 n 是链表的长度。空间复杂度主要取决于递归调用的栈空间,最多为 n 层。
方法一 头插法
所谓头插法,是指在原有链表的基础上,依次将位于链表头部的节点摘下,然后采用从头部插入的方式生成一个新链表,则此链表即为原链表的反转版。
思路
定义一个临时指针指向原链表,创建一个新链表
1、判断链表是否为空,以及一个节点 直接返回原链表
2、两个链表节点以上
原链表head ,临时指针temp,新的空链表newhead
public class Solution {
public ListNode ReverseList(ListNode head) {
ListNode temp = null;
ListNode newhead = null;
if(head==null || head.next==null)
{
return head;
}
while(head !=null )
{
temp = head;
//从原链表中摘除头部节点
head = head.next;
temp.next = newhead;
newhead = temp;
}
return newhead;
}
}
为什么这样的输出只有一个节点
原因 temp和head指向的是同一张链表
temp的链表断开了,同时head指向的链表自然也就断开了,所以只循环一次
我们应该在 temp = head之后,即第二行代码的位置 让首节点即temp断开,原链表指向下一个节点
所以head = head.next 要放在第二行位置