Skip to main content

Command Palette

Search for a command to run...

Solving Leetcode Interviews in Seconds with AI: Disconnect Path in a Binary Matrix by at Most One Flip

Updated
5 min read

Introduction

In this blog post, we will explore how to solve the LeetCode problem "2556" using AI. LeetCode is a popular platform for preparing for coding interviews, and with the help of AI tools like Chatmagic, we can generate solutions quickly and efficiently - helping you pass the interviews and get the job offer without having to study for months.

Problem Statement

You are given a 0-indexed m x n binary matrix grid. You can move from a cell (row, col) to any of the cells (row + 1, col) or (row, col + 1) that has the value 1. The matrix is disconnected if there is no path from (0, 0) to (m - 1, n - 1). You can flip the value of at most one (possibly none) cell. You cannot flip the cells (0, 0) and (m - 1, n - 1). Return true if it is possible to make the matrix disconnect or false otherwise. Note that flipping a cell changes its value from 0 to 1 or from 1 to 0. Example 1: Input: grid = [[1,1,1],[1,0,0],[1,1,1]] Output: true Explanation: We can change the cell shown in the diagram above. There is no path from (0, 0) to (2, 2) in the resulting grid. Example 2: Input: grid = [[1,1,1],[1,0,1],[1,1,1]] Output: false Explanation: It is not possible to change at most one cell such that there is not path from (0, 0) to (2, 2). Constraints: m == grid.length n == grid[i].length 1 <= m, n <= 1000 1 <= m * n <= 105 grid[i][j] is either 0 or 1. grid[0][0] == grid[m - 1][n - 1] == 1

Explanation

Here's a breakdown of the solution approach, followed by the code:

  • Find all paths: Use Depth-First Search (DFS) to find all paths from (0, 0) to (m-1, n-1) without modifying the grid.
  • Path Length 1 and 2 handling: If there's only one path, it must be the direct path (all right, then all down). If this path contains at least one zero (excluding the start/end), flipping that zero will disconnect the grid. Similarly if there are two paths and they share at most one intermediate node, then flipping that intermediate node will disconnect the grid
  • Min Cut: Convert the grid into a flow network. Each cell represents a node. Edges connect adjacent cells (up/down/left/right) that have a value of 1. Calculate the maximum flow (equal to the min cut due to the max-flow min-cut theorem) from (0, 0) to (m-1, n-1). If the min cut is less than or equal to 2, then flipping at most one cell can disconnect the graph.

  • Runtime & Storage Complexity: O(mn), where m and n are the dimensions of the grid. This complexity is primarily due to the min-cut calculation and DFS traversals.

Code

    def isPossibleToCutPath(grid):
    m, n = len(grid), len(grid[0])

    def dfs(row, col, visited):
        if row == m - 1 and col == n - 1:
            return True

        visited[row][col] = True

        # Possible next moves
        moves = [(row + 1, col), (row, col + 1)]

        for next_row, next_col in moves:
            if 0 <= next_row < m and 0 <= next_col < n and grid[next_row][next_col] == 1 and not visited[next_row][next_col]:
                if dfs(next_row, next_col, visited):
                    return True

        return False

    # First DFS to check if a path exists at all
    visited = [[False] * n for _ in range(m)]
    if not dfs(0, 0, visited):
        return True

    def find_all_paths(row, col, current_path, all_paths):
        current_path.append((row,col))

        if row == m - 1 and col == n - 1:
            all_paths.append(current_path[:])
            current_path.pop()
            return

        moves = [(row + 1, col), (row, col + 1)]

        for next_row, next_col in moves:
            if 0 <= next_row < m and 0 <= next_col < n and grid[next_row][next_col] == 1 and (next_row, next_col) not in current_path:
                find_all_paths(next_row, next_col, current_path, all_paths)
        current_path.pop()

    all_paths = []
    find_all_paths(0, 0, [], all_paths)

    if len(all_paths) == 1:
        path = all_paths[0]
        for r, c in path[1:-1]:
            if grid[r][c] == 0:
                return True
        return False # if path contains only 1s

    if len(all_paths) == 2:
        path1 = all_paths[0]
        path2 = all_paths[1]
        shared_nodes = set(path1).intersection(set(path2))

        if len(shared_nodes) <=2: # only (0,0) and (m-1,n-1)
          return True

        intermediate_nodes = shared_nodes - {(0, 0), (m-1, n-1)}

        if len(intermediate_nodes) == 1:
            return True

    # Max Flow/ Min Cut approach
    def solve():
        capacity = [[0] * (m * n) for _ in range(m * n)]

        # Build the capacity matrix
        for r in range(m):
            for c in range(n):
                node_id = r * n + c
                if grid[r][c] == 1:
                    # Connect to neighbors
                    neighbors = [(r + 1, c), (r, c + 1)]
                    for nr, nc in neighbors:
                        if 0 <= nr < m and 0 <= nc < n and grid[nr][nc] == 1:
                            neighbor_id = nr * n + nc
                            capacity[node_id][neighbor_id] = 1

        def bfs(s, t, parent):
            visited = [False] * (m * n)
            queue = [s]
            visited[s] = True

            while queue:
                u = queue.pop(0)
                for ind, val in enumerate(capacity[u]):
                    if visited[ind] is False and val > 0:
                        queue.append(ind)
                        visited[ind] = True
                        parent[ind] = u

            return visited[t]

        def ford_fulkerson(source, sink):
            parent = [-1] * (m * n)
            max_flow = 0

            while bfs(source, sink, parent):
                path_flow = float('inf')
                s = sink
                while s != source:
                    path_flow = min(path_flow, capacity[parent[s]][s])
                    s = parent[s]

                max_flow += path_flow

                v = sink
                while v != source:
                    u = parent[v]
                    capacity[u][v] -= path_flow
                    capacity[v][u] += path_flow
                    v = parent[v]

            return max_flow

        source = 0
        sink = m * n - 1
        max_flow = ford_fulkerson(source, sink)

        return max_flow <= 2

    return solve()

More from this blog

C

Chatmagic blog

2894 posts