3128. Right Triangles
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 1
s: one located in the same row and the other in the same column.
The procedure is as follows:
-
Count
1
s in Rows and Columns: Create two arrays,rows
andcols
, to count the number of1
s in each row and column, respectively. This helps us quickly determine potential placements for the two other vertices of a triangle for any given1
. -
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 byrows[i] - 1
(excluding the current1
itself). - Similarly, the number of potential vertical edges (along column
j
) is given bycols[j] - 1
. - Multiply these two numbers to get the number of potential right triangles with
(i, j)
as the right angle.
- For each
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:
-
Initial Setup: Create two arrays,
rows
andcols
. These arrays will be used to store the count of1
s present in each row and each column of the grid, respectively.rows[i]
will store the count of1
s in thei-th
row.cols[j]
will store the count of1
s in thej-th
column.
-
Counting
1
s: Iterate over each element of the grid. For any1
found at position(i, j)
, incrementrows[i]
andcols[j]
. This step is crucial for fast access to the number of potential connections in rows and columns. -
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]
is1
, the potential triangles using this1
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
.
- Initialize a variable
-
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 EvaluatorExample 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 1
s.
Step 1: Initial Setup
- Create two arrays
rows
andcols
to count the number of1
s per row and column.- Initialize:
rows = [0, 0, 0]
andcols = [0, 0, 0]
- Initialize:
Step 2: Counting 1
s
- Iterate through each element in the grid to count
1
s:- Row 0:
grid[0][0]
is1
, incrementrows[0]
andcols[0]
→rows = [1, 0, 0]
,cols = [1, 0, 0]
grid[0][2]
is1
, incrementrows[0]
andcols[2]
→rows = [2, 0, 0]
,cols = [1, 0, 1]
- Row 1:
grid[1][1]
is1
, incrementrows[1]
andcols[1]
→rows = [2, 1, 0]
,cols = [1, 1, 1]
- Row 2:
grid[2][0]
is1
, incrementrows[2]
andcols[0]
→rows = [2, 1, 1]
,cols = [2, 1, 1]
grid[2][2]
is1
, incrementrows[2]
andcols[2]
→rows = [2, 1, 2]
,cols = [2, 1, 2]
- Row 0:
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]
is1
, potential triangles =(rows[0] - 1) * (cols[0] - 1) = 1 * 1 = 1
grid[0][2]
is1
, potential triangles =(rows[0] - 1) * (cols[2] - 1) = 1 * 1 = 1
grid[1][1]
is1
, potential triangles =(rows[1] - 1) * (cols[1] - 1) = 0 * 0 = 0
grid[2][0]
is1
, potential triangles =(rows[2] - 1) * (cols[0] - 1) = 1 * 1 = 1
grid[2][2]
is1
, 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.
Which algorithm should you use to find a node that is close to the root of the tree?
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Backtracking Template Prereq DFS with States problems dfs_with_states Combinatorial search problems Combinatorial search problems involve finding groupings and assignments of objects that satisfy certain conditions Finding all permutations combinations subsets and solving Sudoku are classic combinatorial problems The time complexity of combinatorial problems often grows rapidly with the size of
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Want a Structured Path to Master System Design Too? Don’t Miss This!