Program to detect cycles in 2D grid in Python

Cycle detection in a 2D grid is a common graph problem where we need to find if there exists a path that starts and ends at the same cell. A cycle must have at least 4 cells and we can only move to adjacent cells with the same character value.

Problem Understanding

Given a 2D grid of characters, we need to detect if there's a cycle. The conditions are ?

  • A cycle has length 4 or more

  • We can move in four directions (up, down, left, right)

  • Adjacent cells must have the same character

  • Cannot revisit cells except the starting cell to complete the cycle

Example Grid

m m m p
m k m m
m m s m
f t m m

The green cells form a cycle, so the output should be True.

Algorithm Approach

We use DFS with three-color marking ?

  • WHITE (0): Unvisited cell

  • GRAY (1): Currently being processed

  • BLACK (2): Completely processed

Implementation

from collections import defaultdict

def detect_cycle_in_grid(grid):
    WHITE, GRAY, BLACK = 0, 1, 2
    R, C = len(grid), len(grid[0])
    
    # Color mapping for each cell
    color = defaultdict(int)
    
    # Direction vectors: up, right, down, left
    directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
    
    def dfs(r, c, parent_r=-1, parent_c=-1):
        color[r, c] = GRAY
        
        for dx, dy in directions:
            nr, nc = r + dx, c + dy
            
            # Check bounds and same character
            if (0 <= nr < R and 0 <= nc < C and 
                grid[r][c] == grid[nr][nc] and 
                (nr, nc) != (parent_r, parent_c)):
                
                if color[nr, nc] == WHITE:
                    if dfs(nr, nc, r, c):
                        return True
                elif color[nr, nc] == GRAY:
                    # Found back edge - cycle detected
                    return True
        
        color[r, c] = BLACK
        return False
    
    # Check each unvisited cell
    for r in range(R):
        for c in range(C):
            if color[r, c] == WHITE:
                if dfs(r, c):
                    return True
    
    return False

# Test with the example grid
grid = [
    ["m", "m", "m", "p"],
    ["m", "k", "m", "m"],
    ["m", "m", "s", "m"],
    ["f", "t", "m", "m"]
]

print(detect_cycle_in_grid(grid))
True

How It Works

The algorithm performs DFS from each unvisited cell ?

  1. Mark as GRAY: When visiting a cell, mark it as currently being processed

  2. Explore neighbors: Check all 4 adjacent cells with the same character

  3. Skip parent: Avoid going back to the immediate parent cell

  4. Detect cycle: If we reach a GRAY cell, we found a back edge (cycle)

  5. Mark as BLACK: After processing all neighbors, mark as completed

Test with Different Grid

# Grid without cycle
grid_no_cycle = [
    ["a", "a", "b"],
    ["a", "b", "b"],
    ["b", "b", "a"]
]

print("Grid without cycle:", detect_cycle_in_grid(grid_no_cycle))

# Grid with cycle
grid_with_cycle = [
    ["a", "a", "a"],
    ["a", "b", "a"],
    ["a", "a", "a"]
]

print("Grid with cycle:", detect_cycle_in_grid(grid_with_cycle))
Grid without cycle: False
Grid with cycle: True

Time and Space Complexity

  • Time Complexity: O(m × n) where m and n are grid dimensions

  • Space Complexity: O(m × n) for the color mapping and recursion stack

Conclusion

This DFS-based approach efficiently detects cycles in 2D grids using three-color marking. The key insight is treating the grid as a graph where edges connect adjacent cells with the same character, then detecting back edges during traversal.

Updated on: 2026-03-26T14:10:35+05:30

341 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements