Facebook Pixel

3128. Right Triangles

MediumArrayHash TableMathCombinatoricsCounting
Leetcode Link

Problem Description

You are given a 2D boolean matrix grid.

A collection of 3 elements of grid is a right triangle if one of its elements is in the same row with another element and in the same column with the third element. The 3 elements may not be next to each other.

Return an integer that is the number of right triangles that can be made with 3 elements of grid such that all of them have a value of 1.

Intuition

To solve this problem, the key is understanding how to count potential right triangles in the grid efficiently. For each 1 in the grid, consider it as the right-angled vertex of a potential right triangle. The other two vertices of this triangle must also be 1s: one located in the same row and the other in the same column.

The procedure is as follows:

  1. Count 1s in Rows and Columns: Create two arrays, rows and cols, to count the number of 1s in each row and column, respectively. This helps us quickly determine potential placements for the two other vertices of a triangle for any given 1.

  2. Enumerate Potential Triangles:

    • For each 1 located at position (i, j), treat it as the right angle of a triangle.
    • The number of potential horizontal edges (along row i) is given by rows[i] - 1 (excluding the current 1 itself).
    • Similarly, the number of potential vertical edges (along column j) is given by cols[j] - 1.
    • Multiply these two numbers to get the number of potential right triangles with (i, j) as the right angle.

By doing the above, you effectively count the number of right triangles that can be formed with each 1 as the right angle, accumulating the total count as you iterate through the grid.

Learn more about Math and Combinatorics patterns.

Solution Approach

The solution employs a technique based on counting and enumeration. Here's a step-by-step breakdown of the approach:

  1. Initial Setup: Create two arrays, rows and cols. These arrays will be used to store the count of 1s present in each row and each column of the grid, respectively.

    • rows[i] will store the count of 1s in the i-th row.
    • cols[j] will store the count of 1s in the j-th column.
  2. Counting 1s: Iterate over each element of the grid. For any 1 found at position (i, j), increment rows[i] and cols[j]. This step is crucial for fast access to the number of potential connections in rows and columns.

  3. Enumerate and Calculate Right Triangles:

    • Initialize a variable ans to keep track of the total number of right triangles.
    • Again, traverse each element of the grid. When a 1 is encountered at (i, j), compute the number of triangles using it as the right angle.
    • If grid[i][j] is 1, the potential triangles using this 1 as a right angle is calculated as:
      • (rows[i] - 1) * (cols[j] - 1)
        • rows[i] - 1 represents potential elements in the same row.
        • cols[j] - 1 represents potential elements in the same column.
    • Add this value to ans.
  4. Return the Result: Finally, return the value of ans.

By considering each 1 as a potential right angle for triangles and calculating possible configurations based on row and column counts, the solution efficiently counts all valid right triangles in the grid.

Ready to land your dream job?

Unlock your dream job with a 2-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through a small example using the provided solution approach.

Consider the following 2D boolean grid:

grid = [
  [1, 0, 1],
  [0, 1, 0],
  [1, 0, 1]
]

In this grid, we want to find all possible right triangles formed by 1s.

Step 1: Initial Setup

  • Create two arrays rows and cols to count the number of 1s per row and column.
    • Initialize: rows = [0, 0, 0] and cols = [0, 0, 0]

Step 2: Counting 1s

  • Iterate through each element in the grid to count 1s:
    • Row 0:
      • grid[0][0] is 1, increment rows[0] and cols[0]rows = [1, 0, 0], cols = [1, 0, 0]
      • grid[0][2] is 1, increment rows[0] and cols[2]rows = [2, 0, 0], cols = [1, 0, 1]
    • Row 1:
      • grid[1][1] is 1, increment rows[1] and cols[1]rows = [2, 1, 0], cols = [1, 1, 1]
    • Row 2:
      • grid[2][0] is 1, increment rows[2] and cols[0]rows = [2, 1, 1], cols = [2, 1, 1]
      • grid[2][2] is 1, increment rows[2] and cols[2]rows = [2, 1, 2], cols = [2, 1, 2]

Now we have the counts:

  • rows = [2, 1, 2]
  • cols = [2, 1, 2]

Step 3: Enumerate and Calculate Right Triangles

  • Initialize ans to 0 to track the number of triangles.

  • For each 1 in the grid, calculate potential right triangles:

    • grid[0][0] is 1, potential triangles = (rows[0] - 1) * (cols[0] - 1) = 1 * 1 = 1
    • grid[0][2] is 1, potential triangles = (rows[0] - 1) * (cols[2] - 1) = 1 * 1 = 1
    • grid[1][1] is 1, potential triangles = (rows[1] - 1) * (cols[1] - 1) = 0 * 0 = 0
    • grid[2][0] is 1, potential triangles = (rows[2] - 1) * (cols[0] - 1) = 1 * 1 = 1
    • grid[2][2] is 1, potential triangles = (rows[2] - 1) * (cols[2] - 1) = 1 * 1 = 1
  • Sum them up: ans = 1 + 1 + 0 + 1 + 1 = 4

Step 4: Return the Result

  • The total number of right triangles in the grid is 4.

Solution Implementation

1from typing import List
2
3class Solution:
4    def numberOfRightTriangles(self, grid: List[List[int]]) -> int:
5        # Initialize row and column count arrays
6        row_counts = [0] * len(grid)  # Count of '1's in each row
7        col_counts = [0] * len(grid[0])  # Count of '1's in each column
8
9        # Count the number of '1's in each row and column
10        for i, row in enumerate(grid):
11            for j, value in enumerate(row):
12                row_counts[i] += value  # Add up '1' count for rows
13                col_counts[j] += value  # Add up '1' count for columns
14
15        triangles = 0  # Initialize right triangle counter
16
17        # Calculate possible right triangles
18        for i, row in enumerate(grid):
19            for j, value in enumerate(row):
20                if value:  # If there is a '1' at this position
21                    # Calculate number of combinations for a right triangle
22                    # Rows and columns can each be endpoints of the triangle
23                    triangles += (row_counts[i] - 1) * (col_counts[j] - 1)
24
25        return triangles
26
1class Solution {
2    public long numberOfRightTriangles(int[][] grid) {
3        int m = grid.length;  // Get the number of rows
4        int n = grid[0].length;  // Get the number of columns
5
6        // Arrays to count the number of 1's in each row and column
7        int[] rowCounts = new int[m];
8        int[] colCounts = new int[n];
9
10        // Count the number of 1's in each row and each column
11        for (int i = 0; i < m; ++i) {
12            for (int j = 0; j < n; ++j) {
13                rowCounts[i] += grid[i][j];  // Increment row count for row i
14                colCounts[j] += grid[i][j];  // Increment column count for column j
15            }
16        }
17
18        long numberOfTriangles = 0;  // Variable to store the total number of right triangles
19
20        // Iterate over each cell in the grid
21        for (int i = 0; i < m; ++i) {
22            for (int j = 0; j < n; ++j) {
23                // Check if the current cell is part of a right triangle (i.e., has a 1)
24                if (grid[i][j] == 1) {
25                    // Compute the number of triangles with current cell as the right angle vertex
26                    // (rows[i] - 1) counts the number of possible horizontal points (excluding the current one)
27                    // (cols[j] - 1) counts the number of possible vertical points (excluding the current one)
28                    numberOfTriangles += (long) (rowCounts[i] - 1) * (colCounts[j] - 1);
29                }
30            }
31        }
32
33        return numberOfTriangles;  // Return the total number of right triangles found
34    }
35}
36
1#include <vector>
2
3class Solution {
4public:
5    long long numberOfRightTriangles(std::vector<std::vector<int>>& grid) {
6        int rowCount = grid.size();             // Number of rows in the grid
7        int colCount = grid[0].size();          // Number of columns in the grid
8      
9        std::vector<int> rowSum(rowCount, 0);   // Array to store the sum of '1's in each row
10        std::vector<int> colSum(colCount, 0);   // Array to store the sum of '1's in each column
11      
12        // Calculate the number of '1's in each row and column
13        for (int row = 0; row < rowCount; ++row) {
14            for (int col = 0; col < colCount; ++col) {
15                if (grid[row][col] == 1) {
16                    rowSum[row]++;
17                    colSum[col]++;
18                }
19            }
20        }
21
22        long long totalTriangles = 0;           // Variable to store the total number of right triangles
23
24        // Iterate through the grid to count potential right triangles
25        for (int row = 0; row < rowCount; ++row) {
26            for (int col = 0; col < colCount; ++col) {
27                if (grid[row][col] == 1) {
28                    // Calculate possible triangles with the current point as the right angle
29                    totalTriangles += (static_cast<long long>(rowSum[row]) - 1) * (static_cast<long long>(colSum[col]) - 1);
30                }
31            }
32        }
33
34        return totalTriangles;                  // Return the total number of right triangles
35    }
36};
37
1/**
2 * Function to count the number of right triangles that can be formed using 1s in a grid.
3 * A valid right triangle has a right angle at one of the 1s, with the other two 1s lying on its row and column respectively.
4 * 
5 * @param grid A 2D array representing the grid.
6 * @returns The number of right triangles possible in the grid.
7 */
8function numberOfRightTriangles(grid: number[][]): number {
9    const numRows = grid.length;  // Number of rows in the grid
10    const numCols = grid[0].length;  // Number of columns in the grid
11  
12    // Arrays to store the count of 1s in each row and each column
13    const rowCount: number[] = Array(numRows).fill(0);
14    const colCount: number[] = Array(numCols).fill(0);
15  
16    // Count 1s in each row and column
17    for (let i = 0; i < numRows; ++i) {
18        for (let j = 0; j < numCols; ++j) {
19            rowCount[i] += grid[i][j];
20            colCount[j] += grid[i][j];
21        }
22    }
23  
24    let totalTriangles = 0;  // Variable to keep track of total number of right triangles
25  
26    // Calculate possible right triangles at each 1 position
27    for (let i = 0; i < numRows; ++i) {
28        for (let j = 0; j < numCols; ++j) {
29            if (grid[i][j] === 1) {
30                // Calculate the number of triangles with right angle at (i, j)
31                // (rowCount[i] - 1) * (colCount[j] - 1) gives the rest of the 1s on the same row and column
32                totalTriangles += (rowCount[i] - 1) * (colCount[j] - 1);
33            }
34        }
35    }
36  
37    return totalTriangles;
38}
39

Time and Space Complexity

The time complexity of the code is O(m * n) because there are two nested loops. The first set of loops calculates the sum of values in each row and each column, iterating over every element in the grid once, which is O(m * n). The second set of nested loops also goes through every grid element once, resulting in a total time complexity of O(m * n).

The space complexity is O(m + n). This is due to the storage of two lists, rows and cols, which store the sum of each row and each column, respectively. The size of rows depends on the number of rows m, and the size of cols depends on the number of columns n. Therefore, the combined space complexity is O(m + n).

Learn more about how to find time and space complexity quickly.


Discover Your Strengths and Weaknesses: Take Our 2-Minute Quiz to Tailor Your Study Plan:
Question 1 out of 10

Which algorithm should you use to find a node that is close to the root of the tree?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!


Load More