剑指 Offer 24. 反转链表
题意
剑指 Offer 24. 反转链表
解法
1. 三指针(双指针)
大概的思路是对于三个连续的节点A->B->C,用三个指针pre,p,tep一一对应。
- 断开B -> C,连接B -> A (此时链表被一分为二,不过 C 节点所在的第二条链表还有tep指针指向,不至于丢失)。
- 然后三个指针都向右移动一个节点,因为tep是最前面的节点,所以需要判断是否为空,不为空则前移。
- 重复第一步。
- p为空时退出循环。
- 原来的head节点的next还指向第二个节点,这里要修改。
这个方法的本质就是将后一个节点重新指向前一个节点实现反转,tep的作用是为了保存剩余节点组成的第二个链表不丢失,依次将第二个链表的值加入第一个链表。
2. 递归
leetcode大佬的一种解法,详情点击# 【反转链表】:双指针,递归,妖魔化的双指针
- 首先通过递归找到最后一个元素
head.next === null
- 每次函数在返回的过程中,让当前结点的下一个结点的
next
指针指向当前节点。 - 同时让当前结点的 next 指针指向 NULL ,从而实现从链表尾部开始的局部反转。
注意
- 这里一旦找到最后一个节点res后,就不会修改res了,只会层层返回res
3. 妖魔化的双指针
leetcode大佬的一种解法,详情点击# 【反转链表】:双指针,递归,妖魔化的双指针
和双指针的思路有相似之处,区别在于怎么记录未反转链表的位置。
代码
1. 三指针(双指针)
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
if(!head)return null
if(!head.next)return head
let pre = head
let p = head.next
let tep = head.next.next
while(p){
p.next = pre
pre = p
p = tep
if(tep)tep = tep.next
}
head.next = null
return pre
};
2. 递归
var reverseList = function(head) {
if(head === null||head.next === null){
return head
}
let res = reverseList(head.next)
head.next.next = head
head.next = null
return res
};
3. 妖魔化的双指针
var reverseList = function(head) {
if(head === null) return null
let p = head
while(head.next !== null){
let tep = head.next.next
head.next.next = p
p = head.next
head.next = tep
}
return p
};