简体   繁体   中英

RuntimeError : dictionary changed size during iteration with defaultdict()

In the code I wrote, an error called RuntimeError: dictionary changed size during iteration occurred in the for i in graph part. although I did not change the graph dictionary at all. I experimented with this as well as if it wasn't possible to use defaultdict in the for statement, but it worked well, the code I experimented is also attached, so can I know why this error came out?

def canFinish(numCourses: int, prerequisites:[[]]) -> bool:
        
        graph = collections.defaultdict(list)
        visited = set()
        
        for i in prerequisites:
            graph[i[0]].append(i[1])
        
        def _dfs(i):
            if i in visited:
                return False
            
            visited.add(i)
            for e in graph[i]:
                if not _dfs(e):
                    return False
            visited.remove(i)
            return True
            
        
        
        for i in graph:
            if not _dfs(i):
                return False
            
        return True
---------------------------------------------------------------------------
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-37-33d660346b1a> in <module>
----> 1 canFinish(3, [[0,1],[0,2],[1,2]])

<ipython-input-36-fd2cb0d8dafb> in canFinish(numCourses, prerequisites)
     20 
     21 
---> 22         for i in graph:
     23             if not _dfs(i):
     24                 return False

RuntimeError: dictionary changed size during iteration


experiment code

a = defaultdict(list)
a[1] = [3,4,5]
a[2]
for q in a:
    print(q)

"""
OUTPUT : 1,2
"""

I can see how your code can add items to graph inside the loop in question...

You are iterating over the items in graph . So let's say graph looks like this:

graph = [g1, g2, g3]

So the loop calls _dfs(g1) . Then, inside _dfs , there's this line:

for e in graph[i]:

so that line is iterating over graph[g1] . That's fine, because that entry exists in graph . But what is in graph[g1] ? We don't know. Let's assume the first key in that collection is x1 . So now e is graph[g1][x1] . Then, _dfs is called again, with this new e :

_dfs(e)

Then inside _dfs , we again do:

for e in graph[i]:

but this time i is graph[g1][x1] , the prior e that was passed in as the parameter to _dfs . So this line is really:

for e in graph[graph[g1][x1]]

We don't know what graph[g1][x1] is. We can't assume that it is a key in graph . If it isn't, then because graph is a defaultdict , an entry is added to graph for the key graph[g1][x1] , with an empty list as the key. This is when graph changes size.

If graph[g1][x1] were already in graph , then I believe that this code would recurse forever.

I don't understand your logic since you haven't shown us the incoming data passed in as prerequisites . Looking just at the code, I can't think of how calling _dfs recursively, and therefore needing items in the value lists of graph to also be keys in graph , would ever make sense. I would suggest that you rethink this aspect of your algorithm.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM