-
Notifications
You must be signed in to change notification settings - Fork 639
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
leetcode206:反转链表 #14
Comments
方法一:遍历
边界条件:
function reverseList(head) {
// 链表只有一个元素时
if( head.next === null ) return head;
// 否则
let current = head.next,
preNode = head;
// 链表反向后原来的头就变成尾了
preNode.pre = null; // 相当于 head.pre = null;
while( current.next ){
current.pre = preNode; // 建立反向联系
// 指针后移
preNode = current;
current = current.next;
}
current.pre = preNode; // 建立最后一个元素和倒数第二个元素的联系
// 至此,一个双向链表已经完成了
// 然后就要开始往前遍历了
while( current.pre ){
// 指向反向
current.next = current.pre;
// 使"先指针"和"后指针"都指向当前对象
preNode = current;
// "先指针"前移
current = current.pre;
// 将初始从前向后遍历时新增的属性删掉
delete preNode.pre;
}
// 修正原链表第一个元素的指向
current.next = current.pre;
delete current.pre;
} 方法二:递归
边界条件:
function reverseList(node) { // 传入链表的头结点
if( node.next === null ) {
/*
* 能走到这里的有只有两种情况:
* 1.链表只有一个元素
* 2.链表不止一个元素同时已经遍历到链表的最后一个元素了
* */
return node;
} else{
const nextNode = reverseList(node.next);
nextNode.next = node;
node.next = null; // 如果不是原链表的第一个元素,则会在上一次递归的作用域中被修改
return node;
}
} 测试代码: function CreateNode(val){
this.val = val;
this.next = null;
}
function CreateList(...nodes){
this.head = nodes[0];
this.length = nodes.length;
for( var i = 0; i < nodes.length - 1; i++ ){
if( nodes[i+1] ){
nodes[i].next = nodes[i+1];
}
}
}
function reverseList(head){
// 选择上面所示的任意一个翻转链表的函数
}
const node1 = new CreateNode(1);
const node2 = new CreateNode(2);
const node3 = new CreateNode(3);
const node4 = new CreateNode(4);
const node5 = new CreateNode(5);
const list = new CreateList(node1, node2, node3, node4, node5);
console.log(node1);
reverseList(node1);
console.log(node5); |
解法一:迭代法解题思路: 将单链表中的每个节点的后继指针指向它的前驱节点即可 画图实现: 画图帮助理解一下 确定边界条件: 当链表为 代码实现: var reverseList = function(head) {
if(!head || !head.next) return head
var prev = null, curr = head
while(curr) {
// 用于临时存储 curr 后继节点
var next = curr.next
// 反转 curr 的后继指针
curr.next = prev
// 变更prev、curr
// 待反转节点指向下一个节点
prev = curr
curr = next
}
head = prev
return head
}; 时间复杂度:O(n) 空间复杂度:O(1) 解法二:尾递归法解题思路: 从头节点开始,递归反转它的每一个节点,直到 代码实现: var reverseList = function(head) {
if(!head || !head.next) return head
head = reverse(null, head)
return head
};
var reverse = function(prev, curr) {
if(!curr) return prev
var next = curr.next
curr.next = prev
return reverse(curr, next)
}; 时间复杂度:O(n) 空间复杂度:O(n) 解法三:递归法解题思路: 不断递归反转当前节点 画图实现: 画图帮助理解一下 代码实现: var reverseList = function(head) {
if(!head || !head.next) return head
var next = head.next
// 递归反转
var reverseHead = reverseList(next)
// 变更指针
next.next = head
head.next = null
return reverseHead
}; 时间复杂度:O(n) 空间复杂度:O(n) |
1 递归甩锅function reverse_digui(head) {
if(!head) return null
if(!head.next) return head
const new_head = reverse_digui(head.next) // 先让 head.next 进行反转
head.next.next = head // 反转完成后, head.next 是新链表的尾节点, 再连接上 head
head.next = null // head 成为新链表的尾节点
return new_head // 返回新链表的首节点
} 2 迭代法 // 当前节点指向上一个节点const reverse_link3 = (head) => {
let pre_node = null
let curr_node = head
while (curr_node) {
const next_node = curr_node.next // 保存下个节点
curr_node.next = pre_node // 当前节点指向上一个节点
// 指针向后滑动
pre_node = curr_node
curr_node = next_node
}
return pre_node
}
|
头插法 |
// nb |
示例:
进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?
附leetcode地址:leetcode
The text was updated successfully, but these errors were encountered: