因为我听说在采访中被问了很多,所以有些事情一直困扰着我。 反转一个单链表。问题是我检查了实现,我想知道我在想的是否可以应用
|data1|->|data2|->|data3|->|data4|->|data5|
此结构是链表的初始条件。我在想什么时候我们想逆转就不会这样;
|data5|->|data4|->|data3|->|data2|->|data1|
因此,在一个将花费 O(n)运行时间的循环中,只需用节点#5 节点#1 的数据>,节点#2 与节点#4 可以完成这项工作吗?
答案 0 :(得分:4)
typedef struct Node
{
char data;
struct Node* next;
} Node;
Node* reverse(Node* root)
{
Node* new_root = 0;
while (root)
{
Node* next = root->next;
root->next = new_root;
new_root = root;
root = next;
}
return new_root;
}
int main()
{
Node d = { 'd', 0 };
Node c = { 'c', &d };
Node b = { 'b', &c };
Node a = { 'a', &b };
Node* root = &a;
root = reverse(root);
return 0;
}
答案 1 :(得分:3)
您的算法要求我们从节点5开始,然后从那里开始向后工作。但它是一个单独的链表 - 这意味着我们没有“后退”指针。即使我们有O(1)访问tail
节点,从节点5到节点4也将是一个O(N)操作,因为我们需要从节点1再次启动才能到达节点4。
因此,对于单链表来说,这不是一个好算法。对于双向链表,我们可以访问后向指针,它会给我们O(N)的复杂性。 (您的算法也不完全与类型无关,因为它要求存储在每个节点中的数据是可复制的或可移动的,以便我们可以交换它。)
答案 2 :(得分:3)
您想要编写方法insert_head
并重复使用它。因此,您从原始列表的头部开始,并附加到新链接列表的头部。因此,原始列表的尾部成为新列表的头部。
这是另一种方法:走原始列表,将节点推入堆栈。然后,当您进入新列表时弹出并insert_at_tail
。
您的算法失败,因为您无法在O(1)
时间内在单个链接列表中向后走。要按照你的建议去做,每个节点都是O(n)
(你每次都要从头部走到你每次获取前一个节点的位置),从而将整个列表反转为{{1} }。
答案 3 :(得分:2)
当被问到时,通常的限制是将列表反转到位,这样除了三个或更少的变量之外你不会使用任何额外的空间。这就是为什么这个问题不是微不足道的原因。因此,您既不能使用递归,也不能使用自己的显式堆栈,也不能使用其他LL(当您走原路时,您将使用LL.addToHead(el)
。)
所以这里有一个很好的答案O(n)时间和O(1)空间:
Node reverse(Node n){//n is head; you may also get the LL
if(null == n || null == n.next)
return n;
Node a=n, b=a.next, c=b.next;
a.next=null; b.next=a;
while(null != c){
a=c;
c=c.next;
a.next=b;
b=a;
}
return b;
}
顺便说一下,你提出的解决方案是O(n ^ 2)
答案 4 :(得分:1)
有一个使用O(n)
空间的O(n)
解决方案。考虑避免在线性时间内访问元素的问题。
答案 5 :(得分:1)
如果列表是异构的,或者节点的大小不相等,那么这个想法将会失败。举个例子:
struct base {
int type;
struct base *next;
};
struct small {
struct base common;
int value;
};
struct big {
struct base common;
char payload[12345];
};
答案 6 :(得分:1)
根据最终输出中的位置,从节点反转数据不是一个好主意,原因有两个:
考虑这个伪代码:
reverse_list(node *head)
{
node *temp;
*temp = head -> next;
head-> next = NULL;
while (temp != NULL) {
swap_nodes(head, temp->next); // this aint copying data from nodes, actual nodes are
swap_nodes(head, temp); // swapped based on its and parents' next pointers
}
}