【问题标题】:Print linkedlist reversely反向打印链表
【发布时间】:2016-12-30 23:16:52
【问题描述】:

我正在研究反向打印链表而不破坏的问题。我的具体问题是,

  1. 想知道是否有其他更好的想法,空间复杂度改进,我目前的空间复杂度是O(n) 使用递归调用堆栈;
  2. 想知道提高算法时间复杂度的任何想法吗?

顺便说一句:如果我当前的代码有任何问题,例如逻辑错误,请随时提出建议。

class LinkedListNode:
    def __init__(self, value, nextNode):
        self.value = value
        self.nextNode = nextNode
    def print_reverse(self):
        if not self.nextNode:
            print self.value
            return
        else:
            self.nextNode.print_reverse()
            print self.value
if __name__ == "__main__":
    head = LinkedListNode('a', LinkedListNode('b', LinkedListNode('c', LinkedListNode('d', None))))
    head.print_reverse()

【问题讨论】:

  • 对于单向喜欢列表,这是您可以获得的最佳复杂性。你可以创建一个双链表(一个指向前一个节点的指针),你将拥有O(1) 用于内存复杂性

标签: python algorithm python-2.7 linked-list


【解决方案1】:

您的print_reverse() 可以简化为:

def print_reverse(self):
    if self.nextNode:
        self.nextNode.print_reverse()
    print(self.value)

我不知道你可以如何改进它,你需要一堆描述,因为这个列表不是双向链接的。但是你可以使用自己的堆栈,这样可以避免递归溢出的风险:

def print_reverse(self):
    stack = [self]
    nextNode = self.nextNode
    while nextNode:
        stack.append(nextNode)
        nextNode = nextNode.nextNode
    while stack:
        print(stack.pop().value)

【讨论】:

    【解决方案2】:

    如果您的LinkedListNode 不是不可变的并且您只关心链表的最终结构,您可以在一次迭代中反转链表,并打印元素同时从末尾重新反转它另一个迭代;这会给你Ө(1) 空间复杂度和Ө(n) 时间复杂度。

    否则,如果您在任何时候都不允许更改任何结构,我认为Ө(n) 空间是您可以获得的最佳空间。


    这是一个 Java 实现:

    class LinkedListNode {
        int data;
        LinkedListNode next;
        LinkedListNode(int data) { this.data = data; }
    }
    
    class LinkedListReversePrintImplementation {
        static void printReversely(LinkedListNode node) {
            LinkedListNode currNode = node,
                           nextNode = node.next,
                           temp;
    
            // Remove the link from first node
            currNode.next = null;
    
            // Reverse the other links
            while (nextNode != null) {
                temp = nextNode.next;
                nextNode.next = currNode;
                currNode = nextNode;
                nextNode = temp;
            }
    
            // `currNode` now contains the last node
            // Initialize the `nextNode` of the reversed linked list
            nextNode = currNode.next;
    
            // Remove the first link again
            currNode.next = null;
    
            // Print the last node
            System.out.println(currNode.data);
    
            // Print the other nodes while re-reversing it
            while (nextNode != null) {
                System.out.println(nextNode.data);
    
                temp = nextNode.next;
                nextNode.next = currNode;
                currNode = nextNode;
                nextNode = temp;
            }
        }
    }
    

    【讨论】:

    • 一脸懵逼,这O(1)空间复杂度怎么算?您不需要将整个列表反向组装吗?
    • @AChampion 它接近O(1),因为您只需要存储要交换的两个值:node1.next = None, node2.next = node1, node3.next = node2。这绝对是恒定的空间复杂度。
    • @Aaron3468 实际上它不接近O(1),它实际上是O(1),因为它是一个渐近分析。
    • @SamedDüzçay 我避免在没有强有力的链接来源的情况下在本网站上发表绝对声明。迂腐在这里很常见,但至少有助于验证我的理解。
    • @AChampion 如果我们谈论的是时间复杂度;两者都是O(n),或者比Θ(n)更好,因为我们也知道下限。关于空间复杂度;这个解决方案是Θ(1),而OP的解决方案是Θ(n)。如果您对 Big-Omega 或 Big-Theta 有任何疑问,可以在这里查看:cathyatseneca.gitbooks.io/data-structures-and-algorithms/…
    【解决方案3】:

    使用 O(n) 空间来反向打印列表不是很好,尤其是如果那是堆栈空间。

    如果你不能修改列表,那么你可以在 O(log N) 空间和 O(N log N) 时间内这样做:

    class LinkedListNode:
        def __init__(self, value, nextNode):
            self.value = value
            self.nextNode = nextNode
    
    def count(list):
        ret=0
        while list:
            ret+=1
            list=list.nextNode
        return ret
    
    def print_reverse(list,size=-1):
        if size<0 and list:
            size=count(list)
    
        while size>1:
            midpoint=size/2
            tail=list
            for _ in xrange(midpoint):
                tail=tail.nextNode
            print_reverse(tail,size-midpoint)
            size=midpoint
        if size>0:
            print list.value
    
    
    head = tail = LinkedListNode(1,None)
    for n in range(2,29):
        tail.nextNode=LinkedListNode(n,None)
        tail=tail.nextNode
    
    print_reverse(head)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-08
      • 1970-01-01
      • 2012-11-19
      • 1970-01-01
      • 2020-09-29
      • 2020-09-05
      • 2021-11-30
      • 1970-01-01
      相关资源
      最近更新 更多