<p>You are given a <strong>0-indexed</strong> integer array <code>arr</code>, and an <code>m x n</code> integer <strong>matrix</strong> <code>mat</code>. <code>arr</code> and <code>mat</code> both contain <strong>all</strong> the integers in the range <code>[1, m * n]</code>.</p>

<p>Go through each index <code>i</code> in <code>arr</code> starting from index <code>0</code> and paint the cell in <code>mat</code> containing the integer <code>arr[i]</code>.</p>

<p>Return <em>the smallest index</em> <code>i</code> <em>at which either a row or a column will be completely painted in</em> <code>mat</code>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="image explanation for example 1" /><img alt="image explanation for example 1" src="https://assets.leetcode.com/uploads/2023/01/18/grid1.jpg" style="width: 321px; height: 81px;" />
<pre>
<strong>Input:</strong> arr = [1,3,4,2], mat = [[1,4],[2,3]]
<strong>Output:</strong> 2
<strong>Explanation:</strong> The moves are shown in order, and both the first row and second column of the matrix become fully painted at arr[2].
</pre>

<p><strong class="example">Example 2:</strong></p>
<img alt="image explanation for example 2" src="https://assets.leetcode.com/uploads/2023/01/18/grid2.jpg" style="width: 601px; height: 121px;" />
<pre>
<strong>Input:</strong> arr = [2,8,7,4,1,3,5,6,9], mat = [[3,2,5],[1,4,6],[8,7,9]]
<strong>Output:</strong> 3
<strong>Explanation:</strong> The second column becomes fully painted at arr[3].
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>m == mat.length</code></li>
	<li><code>n = mat[i].length</code></li>
	<li><code>arr.length == m * n</code></li>
	<li><code>1 &lt;= m, n &lt;= 10<sup>5</sup></code></li>
	<li><code>1 &lt;= m * n &lt;= 10<sup>5</sup></code></li>
	<li><code>1 &lt;= arr[i], mat[r][c] &lt;= m * n</code></li>
	<li>All the integers of <code>arr</code> are <strong>unique</strong>.</li>
	<li>All the integers of <code>mat</code> are <strong>unique</strong>.</li>
</ul>

class Solution:
    def firstCompleteIndex(self, arr: List[int], mat: List[List[int]]) -> int:
        '''
        Problem Statement & Constraints.
        You are given a 0-indexed integer array arr
        and an mxn integer matrix 
        arr and mat both contain all the integers in the range [1, m * n]
        Go through each index i in arr, starting from index 0 and paint the cell in mat
        containing the integer arr[i]
        Return the smallest index i at which either a row or a column will be completely painted in mat

        Intuition & Methodology.
        arr gives us the numbers to paint in order - we must do this in order
        We need to return the index of the row or column, when we reach a point where the entire row and column has been painted

        Naive implementation:
        scan through array, paint the number, check the row and column, where that number is
        if row or column is completley filled: return row or column index
        if not, continue painting

        Bottlenecks
        1. We have to scan through the matrix every time to paint the number
            - We can preprocess the mat array to find the number and it's position
            - we store the number:[i, j] key:value pair into a dictionary
            - this will allow us to paint a number in O(1) time
        2. We check the entire row and column at the painted position
            - can we get away with not checking the entire row and column?
            - what if we store a count, the number of painted cells for each row and column position
            - Then we can check whether all the rows and columns have been painted

        Time & Space Complexity.
        let n = len(arr)
        Time Complexity: O(n)
        Space Complexity: O(m*n)

        '''

        cell_positions = defaultdict(list)
        coloured_count_row = defaultdict(int)
        coloured_count_column = defaultdict(int)

        for i in range(len(mat)):
            for j in range(len(mat[0])):
                cell_positions[mat[i][j]] = (i, j)
        
        print(mat)
        print(cell_positions)

        for index, num in enumerate(arr):
            row_index, column_index = cell_positions[num]
            coloured_count_row[row_index] += 1
            coloured_count_column[column_index] += 1

            if coloured_count_row[row_index] == len(mat[0]):
                return index
            
            if coloured_count_column[column_index] == len(mat):
                return index
        


47635