JavaScript中反转链表的策略
我刚刚艰难地回答了一个简单的面试问题:请把单链表倒过来 虽然我没能及时提供一个有效的答案来挽救这次面试,但事后我还是想出了一个解决办法 我的解决方案正确吗?你会如何用Big Oh分析这个?是否有更有效的方法来反转单链表JavaScript中反转链表的策略,javascript,linked-list,singly-linked-list,Javascript,Linked List,Singly Linked List,我刚刚艰难地回答了一个简单的面试问题:请把单链表倒过来 虽然我没能及时提供一个有效的答案来挽救这次面试,但事后我还是想出了一个解决办法 我的解决方案正确吗?你会如何用Big Oh分析这个?是否有更有效的方法来反转单链表 // reverse a linked list var reverseLinkedList = function(linkedlist) { var node = linkedlist; var previous = null; while(node) {
// reverse a linked list
var reverseLinkedList = function(linkedlist) {
var node = linkedlist;
var previous = null;
while(node) {
// reverse pointer
node.next = previous;
// increment previous to current node
previous = node;
// increment node to next node
if (node.next){
node = node.next
} else {
node = null;
}
}
}
注意:在我搜索类似帖子时,我确实在JavaScript中找到了。我想知道我的代码是否可能(没有
temp
变量)。谢谢。您的代码有几个问题。这应该说明问题
// reverse a linked list
var reverseLinkedList = function(linkedlist) {
var node = linkedlist;
var previous = null;
while(node) {
// save next or you lose it!!!
var save = node.next;
// reverse pointer
node.next = previous;
// increment previous to current node
previous = node;
// increment node to next node or null at end of list
node = save;
}
return previous; // Change the list head !!!
}
linkedlist = reverseLinkedList(linkedlist);
这在时间上是O(n),因为您在每个节点上执行的操作数是恒定的。从概念上讲,没有比这更有效的方法了(就big-O表示法而言,可以进行一些代码优化)
不能超过O(n)的原因是,为了做到这一点,需要跳过一些节点。因为您需要修改每个节点,所以这是不可能的
效率则归结为一个恒定的因素。列表中每个项目可以执行的操作越少,代码执行的速度就越快
我想这样做:
function reverseLinkedList(list, previous){
//We need to use the the current setting of
//list.next before we change it. We could save it in a temp variable,
//or, we could call reverseLinkedList recursively
if(list.next !== null){
reverseLinkedList(list.next, list);
}
//Everything after 'list' is now reversed, so we don't need list.next anymore.
//We passed previous in as an argument, so we can go ahead and set next to that.
list.next = previous;
}
reverseLinkedList(list, null);
当然,这是递归的,因此在空间方面效率很低,但我喜欢递归代码:)
这也不会返回反向链表,但如果这很重要,我们可以很容易地修改它。您可以在O(n)时间内递归地解决这个问题。问题是,您需要知道递归是内存密集型的,因为函数在调用堆栈中累积,直到达到停止条件并开始返回实际内容 我解决这个问题的方法是:
const reverse = (head) => {
if (!head || !head.next) {
return head;
}
let temp = reverse(head.next);
head.next.next = head;
head.next = undefined;
return temp;
}
当reverse()到达列表的末尾时,它将抓取最后一个节点作为新的头,并向后引用每个节点。
//O(n)| O(1)当n是链表中的节点数时
类节点{
构造函数(val){
this.val=val;
this.next=null;
}
}
功能反转ElinkedList(头部){
如果(!head)返回空值;
设p1=头部;
设p2=null;
而(p1){
让temp=p1.next;
p1.next=p2;
p2=p1;
p1=温度;
}
返回p2;
}
常数a=新节点(1);
a、 next=新节点(2);
a、 next.next=新节点(3)
console.log(“当前节点”,a);
console.log(“反转列表”,反转列表(a))
ES6解决方案:
只需跟踪反向列表,并将其添加到tmp中即可
const reverseLinkedList = (head) => {
let reversed = null;
while(head) {
const tmp = head;
head = head.next;
tmp.next = reversed;
reversed = tmp;
}
return reversed;
};
console.log(JSON.stringify(reverseLinkedList({
data: 1,
next: {
data: 2,
next: {
data: 3,
next: {
data: 4,
next: {
data: 5,
next: {
data: 5,
next: {
data: 6
}
}
}
}
}
}
})));
反转SingleLinkedList: 输入:1->2->3->4->5->NULL 输出:5->4->3->2->1->NULL 为了理解解决方案,我们必须跟踪前面的head和后面的变量 例如,在上面的输入头=1;next=2我们没有previous,所以假设previous=null 循环列表,直到head不为空。颠倒头部的连接(上一个和下一个)。 下面是代码
var reverseList=函数(头){
让previous=null;
while(head!==null){
让next=head.next;
head.next=上一个;
上一个=头
头=下一个;
}
返回上一个;
};代码>感谢您的回答和对Big-O的分析,非常感谢。