题目描述:
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例:
解法一:利用双指针
看图:
- 首先创建一个temp空结点,用来实现链表的反向连接。
ListNode empty = null;
- 然后创建一个结点变量,用来在head结点反向连接之前,保存下一个结点。
- 在head结点指向前面的结点
- 移动temp到head
- 移动head到提前保存的下一个结点
//保存head的下一个
temp = head.next;
//反转
head.next = empty;
//让上一个指针 走到head
empty = head;
//让head变为temp
head = temp;`
- 然后保存下一个结点
- 在进行相同的操作即可
代码:
public static ListNode reverseList(ListNode head) {
//如果链表为空,则直接返回空
if (head == null) {
return null;
}
//反转后的尾节点 为空
ListNode empty = null;
//保存head的下一个节点
ListNode temp = new ListNode();
while (head != null) {//如果头结点不为空
//保存head的下一个
temp = head.next;
//反转
head.next = empty;
//让上一个指针 走到head
empty = head;
//让head变为temp
head = temp;
}
return empty;
}
解答二:递归实现
递归代码简单,但理解起来有点困难,需要大家画图理解。
先给出代码,然后给出解析、
代码:
public static ListNode reverseList2(ListNode head) {
if (head == null || head.next == null) {
return head;
}
//返回后面反转好的链表
ListNode p = reverseList2(head.next);
//反转这一个点,让下一个结点指向自己,即完成了反转
head.next.next = head;
//这一步是为了让原来的头节点的下一个结点为空。
head.next = null;
return p;
}
首先大家思考一个问题,如果后面的已经反转好了。如上图所示,
我们只要让4指向3即可。
然后让3指向2
再让2指向1
此时是不是已经完成反转了呢??
其实并没有,因为此时1的next还指向2,并没有指向null,
所以如上图所示,我们只需要在反转后断开向后的指向即可,让它指向null,那么当2指向1以后,1指向null即可。
那有怎么返回反转后的头结点呢?
我们只需要让程序递归到head.next==null的时候返回这个结点,这个结点就是反转后的头节点,我们新建一个结点将他保存起来,不存过程如何,我们始终返回头节点即可,最后递归以后返回的依然是头结点。
看下图:
每次返回的都是反转后的头结点,大家可以结合图片和代码,自己画画。