如何向后阅读单链表?

Lea*_*ner 11 c# singly-linked-list

我能想到的一种方法是反转列表然后阅读它.但这涉及改变不好的清单.
或者我可以复制列表然后将其反转,但这会使用额外的O(n)内存.有没有更好的方法不使用额外的内存,不修改列表并在O(n)时间运行

反向链表代码在c#中是这样的

Void Reverse (Node head)
{
    Node prev= null;
    Node current = head;
    Node nextNode = null;

        while (current!=null)
        {
            nextNode = current.Next;
            current.Next = prev;
            prev=current;
            current = nextNode; 

        }
        head = prev;

}   
Run Code Online (Sandbox Code Playgroud)

递归解决方案是

void ReadBackWard (Node n)
{
    if (n==null)
        return;
    else
        ReadBackward(n.Next);

    Console.WriteLine(n.Data);

}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ell 32

要使用O(n)内存和O(n)性能,请创建堆栈; 在向前方向迭代时按下所有内容,然后将所有内容弹出,产生结果.

要使用O(n ^ 2)性能(但是O(1)额外内存),每次都要向前读取它,直到最后一个节点之前的节点.

例:

IEnumerable<T> Reverse (Node head) {
    Stack<Node> nodes = new Stack<Node>();
    while(head != null) {
        nodes.Push(head);
        head = head.Next;
    }
    while(nodes.Count > 0) {
        yield return nodes.Pop().Value;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 使用递归,您通常还需要推送表示调用位置的其他状态.使用显式堆栈通常*效率更高. (7认同)
  • 这与递归基本相同.唯一的区别是显式堆栈与递归的隐式堆栈. (6认同)
  • 不必要.您只需将指针推到堆栈上,而不是整个项目. (4认同)
  • 这是一个更好的解决方案,但它使用相同的O(n)内存,这与拥有列表副本并将其反转并读取它相同 (2认同)

Wil*_*and 10

单链表的标志之一是它实际上是单独链接的.这是一条单行道,除非你把它变成别的东西(比如一个反向的单链表,一个堆栈,一个双向链表......),否则就没办法克服它.一个人必须忠于事物的本质.

正如前面已经指出的那样; 如果你需要双向遍历列表; 你需要有一个双向链表.这是双重链表的本质,它是双向的.


san*_*ity 8

你真的应该使用双向链表.

如果这是不可能的,我认为你最好的选择是构建一个已被反转的列表的副本.

其他选项,例如依赖递归(有效地将列表复制到堆栈)可能会导致如果列表太长则耗尽堆栈空间.

  • 看标签 - "面试问题":) (4认同)
  • 我认为将列表更改为双向链表并不是很糟糕,因为它提出了解决问题的其他机制. (2认同)