「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战」
给定单链表的头节点 head
,请反转链表,并返回反转后的链表的头节点。
示例 1:
输入: head = [1,2,3,4,5]
输出: [5,4,3,2,1]
示例 2:
输入: head = [1,2]
输出: [2,1]
示例 3:
输入: head = []
输出: []
这里我们先说第一种方法:
-
初始化一个变量
vhead = null
; -
循环链表,新建一个链表节点
node
,val
值 = 当前节点的val
,将node
节点的next
指向vhead
,将vhead
=node
,如此循环知道链表的尾结点 -
最后返回
vhead
即可
至此,我们的第一种解题思路就完成了,以下是代码实现
var reverseList = function(head) {
let vhead = null,
cur = head;
while(cur){
const node = new ListNode(cur.val);
node .next = vhead;
vhead = node;
cur = cur.next;
}
return vhead;
}
但是上面这种方法,我们创建了对应数量的节点,并开辟了额外的存储空间存储结果链表,那有没有办法可以直接在原链表上操作即可翻转链表呢?
这里我们说一下第二种方法:
- 题目给定的链表为单向链表,我们可以把链表调整为双向链表,即之前每个节点有一个
next
属性指向它的下一个节点,链表遍历只能从头节点到尾节点,双向链表即每个节点除了next
属性还有一个pre
属性(或者其他什么名字),指向它的上一个节点 - 然后我们定义两个指针,
pre
指向头节点,next
指向尾结点,交换两个指针的值,然后pre
向后移动一位,next
向前移动一位,再交换两个指针的值,知道两个指针相遇 - 最后返回
head
节点即可
至此,我们的第二种解题思路就完成了,以下是代码实现
var reverseList = function(head) {
if(head === null) return null;
let pre = head,
next = head.next;
while(next){
next.pre = pre;
pre = pre.next;
next = next.next;
}
next = pre,pre = head;
while(next !== pre && pre.pre !== next){
const nextVal = next.val;
next.val = pre.val;
pre.val = nextVal;
pre = pre.next;
next = next.pre;
}
return head;
}
至此,我们就完成了leetcode-剑指offer24-翻转链表
如有任何问题或建议,欢迎留言讨论!