【问题标题】:"Time limit exceeded" when changing order of assignment in python更改python中的分配顺序时“超出时间限制”
【发布时间】:2020-12-20 03:13:24
【问题描述】:

我正在处理链接列表中 k 个节点的问题反转组。在写赋值操作做反转的时候,我给了:

cur, cur.next, prev = cur.next, prev, cur

其中curprev 表示当前和以前的节点。发生的最有趣的事情是,当我给予:

cur.next, cur, prev = prev, cur.next, cur

接受,但前者给了我超过时间限制。

我相信 Python 对多个变量的赋值将它们作为元组,并且只考虑所有变量的先前值。那么这两个陈述应该是完全相同的吧?还是我错了?请在这里帮助我。

这是一个 leetcode 问题,我提供整个代码以防万一。该行标有 3 *,如果我单独更改该行,代码将从接受跳转到超出时间限制。

 h=jump=ListNode(0)
 h.next=left=right=head
 while True:
            i=0
            while i<k and right:
                i+=1
                right=right.next
            if i==k:
                prev=right
                cur=left
                for _ in range(k):
                    ***cur.next, cur, prev = prev, cur.next, cur***
                jump.next,jump,left=prev,left,right
            else:
                return h.next

以上代码被接受。只有当我更改线路时,它才会陷入循环,超出时间限制。

【问题讨论】:

  • 您是否阅读过有关此类作业的文档?
  • “TLE”和“AC”是什么意思?请避免使用不必要的首字母缩略词,除非它们非常常见。清晰在这里至关重要。请参阅How to Ask
  • cur.next 的含义会根据cur 的新值是否已经分配而改变。所以是的,分配的顺序在这里很重要。
  • @Chris 对不起,TLE 表示已超过时间限制,而 AC 表示已接受。我认为首字母缩略词很常见,将相应编辑
  • @jasonharper 在 python 中,赋值不是作为某种元组操作完成的。因此,每个值都将分配给它们在整个分配之前的值。这就是为什么只交换 a[i],a[j]=a[j],a[i] 在 python 中就足够了,对吧?

标签: python assignment-operator


【解决方案1】:

分配是from left to right,所以...

cur, cur.next, ... = ...

上面首先分配给cur。然后到cur.next,其中cur已经是新值

cur.next, cur, ... = ...

这首先分配给cur.next,其中cur 仍然是旧值。然后到cur

所以这就是你的不同之处。你改变不同节点的.next

【讨论】:

    【解决方案2】:

    很好的问题!

    现在我也明白这个问题了! (^_^)

    这是链表中非常常见的问题,我们在遍历链表或执行任何其他操作时,应始终注意语句的更改顺序。

    问题是,如果我们的语句中某些必需的顺序被遗漏(这里就是这种情况),最终会发生以下两种情况之一:

    • 如果您愿意,任何一个节点都会错过到下一个节点的链接,并且该节点将变为无链接;
    • 或者一个节点会链接回它自己(像一个圆圈)并且列表将变得过时;

    您的代码具有正确的顺序可以在不超过时间限制的情况下正常工作(刚刚测试):

    # Definition for singly-linked list.
    # class ListNode(object):
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution(object):
        def reverseKGroup(self, head, k):
            """
            :type head: ListNode
            :type k: int
            :rtype: ListNode
            """
            h = jump = ListNode(0)
            h.next = left = right = head
            while True:
                i = 0
                while i < k and right:
                    i += 1
                    right = right.next
                if i == k:
                    prev = right
                    cur = left
                    for _ in range(k):
                        cur.next, cur, prev = prev, cur.next, cur
                    jump.next, jump, left = prev, left, right
                else:
                    return h.next
    
    

    我们也可以使用辅助函数。这将在没有超过时间限制 (TLE) 的情况下通过:

    class Solution:
        def reverseKGroup(self, head, k):
            def rev(head, count):
                prev, curr, next = None, head, head
                while count > 0:
                    next = curr.next
                    curr.next = prev
                    prev, curr, count = curr, next, count - 1
                return (curr, prev)
            count, curr = 0, head
            while curr and count < k:
                curr, count = curr.next, count + 1
            if count < k:
                return head
            new_head, prev = rev(head, count)
            head.next = self.reverseKGroup(new_head, k)
            return prev
    

    这里是 LeetCode 的官方解决方案,带有解释性 cmets:

    递归

    class Solution:
        
        def reverseLinkedList(self, head, k):
            
            # Reverse k nodes of the given linked list.
            # This function assumes that the list contains 
            # atleast k nodes.
            new_head, ptr = None, head
            while k:
                
                # Keep track of the next node to process in the
                # original list
                next_node = ptr.next
                
                # Insert the node pointed to by "ptr"
                # at the beginning of the reversed list
                ptr.next = new_head
                new_head = ptr
                
                # Move on to the next node
                ptr = next_node
                
                # Decrement the count of nodes to be reversed by 1
                k -= 1
            
            # Return the head of the reversed list
            return new_head
                    
        
        def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
            
            count = 0
            ptr = head
            
            # First, see if there are atleast k nodes
            # left in the linked list.
            while count < k and ptr:
                ptr = ptr.next
                count += 1
            
            # If we have k nodes, then we reverse them
            if count == k: 
                
                # Reverse the first k nodes of the list and
                # get the reversed list's head.
                reversedHead = self.reverseLinkedList(head, k)
                
                # Now recurse on the remaining linked list. Since
                # our recursion returns the head of the overall processed
                # list, we use that and the "original" head of the "k" nodes
                # to re-wire the connections.
                head.next = self.reverseKGroup(ptr, k)
                return reversedHead
            return head
    
    

    迭代

    class Solution:
        
        def reverseLinkedList(self, head, k):
            
            # Reverse k nodes of the given linked list.
            # This function assumes that the list contains 
            # atleast k nodes.
            new_head, ptr = None, head
            while k:
                
                # Keep track of the next node to process in the
                # original list
                next_node = ptr.next
                
                # Insert the node pointed to by "ptr"
                # at the beginning of the reversed list
                ptr.next = new_head
                new_head = ptr
                
                # Move on to the next node
                ptr = next_node
                
                # Decrement the count of nodes to be reversed by 1
                k -= 1
            
            # Return the head of the reversed list
            return new_head
                    
        
        def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
            
            ptr = head
            ktail = None
            
            # Head of the final, moified linked list
            new_head = None
            
            # Keep going until there are nodes in the list
            while ptr:
                count = 0
                
                # Start counting nodes from the head
                ptr = head
                
                # Find the head of the next k nodes
                while count < k and ptr:
                    ptr = ptr.next
                    count += 1
    
                # If we counted k nodes, reverse them        
                if count == k:
                    
                    # Reverse k nodes and get the new head
                    revHead = self.reverseLinkedList(head, k)
                    
                    # new_head is the head of the final linked list
                    if not new_head:
                        new_head = revHead
                    
                    # ktail is the tail of the previous block of 
                    # reversed k nodes
                    if ktail:
                        ktail.next = revHead
                        
                    ktail = head 
                    head = ptr
            
            # attach the final, possibly un-reversed portion
            if ktail:
                ktail.next = head
            
            return new_head if new_head else head
    

    参考文献

    • 有关更多详细信息,请参阅Discussion Board,您可以在其中找到大量解释清楚且公认的解决方案,其中包含各种languages,包括低复杂度算法和渐近runtime/memory 分析@ 987654325@, 2.

    【讨论】:

    • 嘿,非常感谢!但是我给出的代码被接受了,上面给出了必须更改的行。如果标有 *** 的行更改为前一行,则不接受该代码。谢谢你的时间,但你能帮我吗
    • 您能否解释一下在这种特殊情况下订单的重要性?在两个语句中,所有 3 个变量都分配给相同的变量。在 python 中,它首先在赋值之前取原始值,对吗?这就是交换 a,b=b,a 有效的原因。很抱歉打扰您,您能解释一下吗?
    • 哦对,明白了!非常感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多