Skip to content
Advertisement

Is it possible to do a depth first search iteratively without copying visited nodes?

Background

  • I am searching a 2D grid for a word.
  • We can search left/right and up/down.
  • For example, in this grid, searching for "abef" starting at (0,0) will return True

Example (grid1):

Grid 1

Where I’m at

  • The recursive version gives expected results (see dfs_rec() below).
  • The iterative version also gives expected results (see dfs_iter() below). However, in this version I am making a copy of the visited set onto the stack at every node.

My question is

  • Is there a way to avoid the copy (visited.copy()) in the iterative version, and add/remove to a single visited set as in the recursive version?

Further details and stuff I’ve tried…

  • In dfs_rec() there is a single set() named visited, and it’s changed via visited.add((row,col)) and visited.remove((row,col))

  • But in dfs_iter() I am pushing visited.copy() onto the stack each time, to prevent nodes from being marked as visited incorrectly.

  • I have seen some iterative examples where they use a single visited set, without making copies or removing anything from the set, but that does not give me the right output in these examples (see dfs_iter_nocopy() using grid3 below).

As an example, take this grid:

Grid 2

  • Say you search for "abexxxxxx" (covering the entire grid), the expected output will be True

Grid 2a

  • But dfs_iter_nocopy() will give incorrect output on one of grid2 or grid3 (they are just mirrored, one will pass and one will fail), depending on the order you push nodes onto the stack.

  • What’s happening is, when you search for "abexxxxxx", it searches a path like this (only hitting 5 x’s, while it needs 6).

Grid 2b

  • It marks the x at (1,0) as visited, and when it’s time to search that branch, it stops at (1,0), like this:

Grid 2c

Code

JavaScript

Advertisement

Answer

You noticed that the recursive version was able to use a single visited accumulator by resetting it with visited.remove((row,col)) when backtracking. So the same can be done here by imitating the function call stack so that we know when backtracking occurs.

JavaScript

The depth will increase as a new tile is explored, but decrease as we exhaust the possibilities for a particular path and revert to an earlier fork. This is what I mean by backtracking.

edit: variable name

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement