Skip to content

Instantly share code, notes, and snippets.

@vgmoose
Last active April 14, 2022 08:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save vgmoose/a15b7eab190abbf721ec to your computer and use it in GitHub Desktop.
Save vgmoose/a15b7eab190abbf721ec to your computer and use it in GitHub Desktop.
number of islands in a bitmap
# initial island map
bitmap = [
[0,0,1,1,0,0,0,1,0,0],
[0,1,1,0,0,1,1,1,0,0],
[0,1,0,0,0,0,0,0,0,0],
[0,0,0,1,1,1,0,0,1,1],
[0,0,0,0,1,1,1,1,1,0],
[0,1,1,0,0,0,0,0,0,0]
]
# get size and initialize count
count = 0
height = len(bitmap)
width = len(bitmap[0])
# create an empty copy of the grid with all Falses
# we will use this to keep track of which nodes we have already
# visited (and therefore, which islands we have already counted)
visited = [[False]*width for x in range(0, height)]
# this recursive function looks at all surrounding up, down, left, right
# tiles and tries to visit them if they contain a land
# (this algorithm is known as "FloodFill")
def visitAll(x, y):
# base case: we're at a water cell, or we've already visited this cell
if not bitmap[x][y] or visited[x][y]:
return
# mark this cell as seen in our visited grid, so we know for later
visited[x][y] = True
# go through up, down, left, and right cells (abs(i) != abs(j)) means we won't hit
# any of the diagonals, nor the center
for i in range(-1, 2):
for j in range(-1, 2):
# also make sure that the new coordinate is actually in bounds
# on the grid (not less than 0 or greater than width/height)
if abs(i) != abs(j) and x+i>=0 and y+j>=0 and x+i<height and y+j<width:
visitAll(x+i, y+j)
# go through all cells in the grid and attempt to visit them
# this will take O(N^2) runtime, but it won't waste time going
# into any cells that we've already visited
for x in range(0, height):
for y in range(0, width):
# already visited this one at an earlier run (via the recursive
# function above), so skip it
if visited[x][y]:
continue
# found a land cell! Increase our count, and mark its adjacent
# cells as already visited as well
if bitmap[x][y]:
visitAll(x, y)
count += 1
# print the total count, which only ever increased when we hit a "new"
# land cell. Since visitAll visited all the neighboring land cells (aka an
# island) and stopped us from double-counting any land cells, this value
# is also the total amount of islands.
print(count)
@5802thiene
Copy link

hello sir, sorry to bother you, i found your code but i don't really understand, could you please explain step by step?

@vgmoose
Copy link
Author

vgmoose commented Apr 1, 2022

Hi! I went through and added comments to the code. Also, I noticed there was an error with it... Thanks for asking so I could see that, and also sorry for that confusion. It's also important to note that this code uses the fact that 0 == False and 1 == True.

The error was that that checking x != y doesn't make sense. What this check should do instead is abs(i) != abs(j). This is how the fix looks in the code.

This approach to check four directions with a nested loop is not great. Doing for i, j in [(-1, 0), (1, 0), (0, -1), (0, 1)]: is cleaner and easier to read, and avoids this bug.

Here's the above code on a similar leetcode question: https://leetcode.com/submissions/detail/671874157/
Using the array instead is a little faster: https://leetcode.com/submissions/detail/671876596/ (no wasted time visiting and skipping diagonals)

This approach still uses a lot of memory however, to store the whole visited copy of the grid. You can get around this by re-using the same variable (although, this will alter the input data. That could be undone after the count is obtained, if needed).

Re-using the original grid as the visited grid as well ("2" means visited, "0"=water, "1"=land): https://leetcode.com/submissions/detail/671879624

The main algorithm used here is Flood Fill, so at each cell of the grid it tries to visit the entire island and increase the island count, then tries to not revisited previously visited (counted) land cells.

@vgmoose
Copy link
Author

vgmoose commented Apr 1, 2022

To view the above leetcode links, you may need to sign in.

This is the similar question: https://leetcode.com/problems/number-of-islands/

@5802thiene
Copy link

5802thiene commented Apr 14, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment