【发布时间】:2021-06-21 09:49:20
【问题描述】:
我正在阅读《Cracking the Coding Interview》并做练习题,但我被困在了这个问题上:
“实现一个算法来删除中间的节点(即除第一个和最后一个节点之外的任何节点,不一定是确切的中间)或单链表,只允许访问该节点。
EXAMPLE 输入:链表中的节点 a->b->c->d->e->f 结果:没有返回任何内容,但是新的链表看起来像 a->b->d-> e->f"
void solution1(Node* node)
{
if (node == NULL || node->next == NULL) {
return;
} else {
Node* ptr = node;
//ptr is the node accessible
Node* ptr2 = ptr->next;
ptr->data = ptr2->data;
ptr->next = ptr2->next;
delete ptr2;
}
cout << "updated list is" << endl;
display();
}
我实现了这个功能,但我想确认它的复杂性。这将是 O(1) 空间和 O(1) 时间复杂度,对吧? 另外,如果我们想删除最后一个节点,我们如何使用一个虚拟节点呢?
【问题讨论】:
-
请每个问题回答一个问题。为什么它与
O(1)有什么不同?没有循环,没有调用其他函数(除了display,我假设实际上是O(N)) -
这不适用于最后一个列表节点。此外,它违背了使用动态节点链接范例的目的。理想情况下,通过从列表中修剪节点来删除节点,将引用它的指针在列表中(例如,某个节点的
next指针或列表head指针)设置为about-to-被删除节点的next成员值。那时您可以删除现在孤立的节点并完成。简而言之,理想情况下,在像这样的列表管理操作期间,唯一需要使用的成员是头指针或列表中的next成员; 没有别的.... -
...但是您无法使用提供的有限数据来做到这一点。例如中间某处的按值节点指针。您无法获取指向相关节点的
next(或head),因此您可以执行的操作受到严重限制。简短版:残酷的任务,但也许你会从中有所收获。 -
请注意,这是糟糕的 C++ 设计。问题出在
ptr->data=ptr2->data;行,它没有考虑异常安全。看来你想要std::move_if_noexcept那里。这并不意味着在算法介绍课上这是一个糟糕的问题——你必须从某个地方开始学习。但对于生产代码,请坚持使用std::forward_list<T> -
@msalters 它可能是(但我们缺少代码)一个带有两个指针的结构,所以不需要移动任何东西。不删除数据可能是也可能不是错误。变量的名称,更重要的是函数的名称……需要改进。
标签: c++ linked-list singly-linked-list