题目要求:
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
解法一
新建一个链表,然后从原链表的头结点开始遍历,把每个元素头插进新的链表,最后返回新链表的头结点
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null){
//如果头结点为空,或者只有一个结点,则没必要反转
return head;
}
ListNode node = head;
ListNode newNode = null;//存储新链表的头结点
while(node != null){
//把原链表的每一个元素都插入到新链表的第一个位置
newNode = new ListNode(node.val, newNode);
node = node.next;
}
return newNode;//返回新链表的头结点
}
时间复杂度和空间复杂度都是O(n)
解法二
利用迭代解决:用三个指针,cur
指向结点,prev
指向结点的前驱,next
保存后继结点的地址
使cur.next
指向prev
,然后后移重复上述操作
代码实现:
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode prev = null;//保存前驱结点
ListNode cur = head;//待反转结点
while(cur != null){
ListNode next = cur.next;//在循环内部定义,确保next不会空指针访问
cur.next = prev;//反转
prev = cur;
cur = next;
}
//循环结束后prev正好停在最后一个结点,返回prev即可
return prev;
}
时间复杂度O(n)、空间复杂度O(1)
解法三
递归解决问题
该递归方法的语义即作用是:传入一个链表的头结点,返回反转后的链表的头结点
当前我们只知道头结点head
,如果头结点为空或者只有一个头结点,则无需反转,直接返回,否则保存头结点的后继结点node
,然后把头结点之后的结点head.next
作为子链表交给递归方法解决,返回值用新的头结点接收
接着把头结点head
接在原后继结点node
后面,这里有一点需要注意,head.next
依然是node
,因此我们需要把这个连接断开,否则链表为空
最后返回新的头结点即可
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode node = head.next;
ListNode newHead = reverseList(head.next);
node.next = head;
head.next = null;//断开头结点后node的连接
return newHead;
}