很有可能。我想出了一个可能不是最佳的解决方案,但表明它可以完成。先把它拆成两个问题:反转next指针和反转随机指针。
反转下一个指针:
node* last = NULL;
node* current = head;
node* next = head->next;
while (current != NULL)
{
current->next = last;
last = current;
current = next;
if (current != NULL)
next = current->next;
}
head = last
反转随机列表有点棘手,因为我们没有随机指针链的所有头的列表,但我们可以找到它们的末端(节点将是一个 NULL 随机指针)。我们将需要几个辅助函数来完成它。第一个是反转随机列表。我们主要从上面复制代码。请注意,我们将链的末端设置为特殊值。这会阻止我们重新反转列表。有关解释,请参阅 cmets 中的讨论。
node* chainTail = malloc(1); //mallocing here to get a unique pointer
void reverseRandom(node* rhead)
{
node* last = chainTail;
node* current = rhead;
node* next = rhead->random;
while (current != NULL)
{
current->random = last;
last = current;
current = next;
if (current != NULL)
next = current->random;
}
}
我们还需要一个辅助函数来查找节点的父节点(如果没有,则返回 NULL)。我们将做一个愚蠢的线性搜索:
node* findParent(node* target)
{
node* candidate = head;
while ((candidate != NULL) && (candidate->random != target))
candidate = candidate->next;
return candidate;
}
现在我们只需遍历列表,找到随机值为 NULL 的任何节点(我们的链尾),找到它们的链头,然后反转链:
node* current = head; //Current node in a linear walk looking for chain tails
while (current != NULL)
{
if (NULL == current->random)
{
//current is the tail of a random chain, lets find the head
node* curr = current; //Current node in the search for the chain hean
node* parent = findParent(curr);
while (parent != NULL)
{
curr = parent;
parent = findParent(curr);
}
//At this point, curr is the head of the random chain, so reverse it
reverseRandom(curr);
}
current = current->next;
}
//Clean up chainTail pointers
node* current;
for (current = head; current != NULL; current = current->next)
{
if (current->random == chainTail)
{
current->random = NULL;
}
}
free(chainTail); //Stop a memory leak if this is not a global
标准免责声明:我没有运行此代码。它可能有错误。快结束的时候我开始昏昏欲睡,所以我可能犯了一个逻辑错误,但在我看来它是有效的。
此外,如果您希望将其投入生产,请不要这样做。这段代码在 O(n^3) 附近运行。这很可能不是最快的解决方案。它确实使用了常量空间(尽管可以通过内联和积极的变量共享来减少)。