Length of Longest V-Shaped Diagonal Segment
HardPrompt
You are given a 2D integer matrix grid of size n x m, where each element is either 0, 1, or 2.
A V-shaped diagonal segment is defined as:
- The segment starts with
1. - The subsequent elements follow this infinite sequence:
2, 0, 2, 0, .... - The segment:
- Starts along a diagonal direction (top-left to bottom-right, bottom-right to top-left, top-right to bottom-left, or bottom-left to top-right).
- Continues the sequence in the same diagonal direction.
- Makes at most one clockwise 90-degree turn to another diagonal direction while maintaining the sequence.

Return the length of the longest V-shaped diagonal segment. If no valid segment exists, return 0.
Example 1:
Input: grid = [[2,2,1,2,2],[2,0,2,2,0],[2,0,1,1,0],[1,0,2,2,2],[2,0,0,2,2]]
Output: 5
Explanation:

The longest V-shaped diagonal segment has a length of 5 and follows these coordinates: (0,2) → (1,3) → (2,4), takes a 90-degree clockwise turn at (2,4), and continues as (3,3) → (4,2).
Example 2:
Input: grid = [[2,2,2,2,2],[2,0,2,2,0],[2,0,1,1,0],[1,0,2,2,2],[2,0,0,2,2]]
Output: 4
Explanation:

The longest V-shaped diagonal segment has a length of 4 and follows these coordinates: (2,3) → (3,2), takes a 90-degree clockwise turn at (3,2), and continues as (2,1) → (1,0).
Example 3:
Input: grid = [[1,2,2,2,2],[2,2,2,2,0],[2,0,0,0,0],[0,0,2,2,2],[2,0,0,2,0]]
Output: 5
Explanation:

The longest V-shaped diagonal segment has a length of 5 and follows these coordinates: (0,0) → (1,1) → (2,2) → (3,3) → (4,4).
Example 4:
Input: grid = [[1]]
Output: 1
Explanation:
The longest V-shaped diagonal segment has a length of 1 and follows these coordinates: (0,0).
Constraints:
n == grid.lengthm == grid[i].length1 <= n, m <= 500grid[i][j]is either0,1or2.
Approaches
2 approaches with complexity analysis and trade-offs.
This approach improves upon a pure brute-force solution by using dynamic programming to pre-calculate the lengths of all possible straight diagonal segments that start with a 1 and follow the required sequence. After this pre-computation, it iterates through every cell, considering it as a potential turning point for a V-shape. For each potential turn, it combines a pre-calculated segment (the first leg) with a second leg whose length is found by iterative traversal.
Algorithm
- Initialize
maxLength = 0. - Define a helper function
getExpectedValue(index)that returns the expected grid value for a given position in the sequence (1for index 0,2for odd indices > 0,0for even indices > 0). - Create four 2D DP arrays of size
n x m:L_tl,L_tr,L_bl,L_brto store lengths of straight segments ending at(r, c)from the four diagonal directions. - Pre-computation Pass:
- Calculate
L_tlandL_trby iteratingrfrom0ton-1andcfrom0tom-1. - Calculate
L_blandL_brby iteratingrfromn-1to0andcfromm-1to0(or any other valid traversal order). - For each cell
(r, c), update the DP value based on the previous diagonal cell's DP value andgrid[r][c]. Ifgrid[r][c] == 1, a new segment of length 1 starts. - Update
maxLength = max(maxLength, dp_value)after each calculation.
- Calculate
- V-Shape Pass:
- Iterate through each cell
(r, c)from(0, 0)to(n-1, m-1). - For each of the four incoming directions (e.g., from Top-Left):
a. Get the length of the first leg,
len1, from the corresponding DP table (e.g.,L_tl[r][c]). b. Iflen1 > 0: i. Determine the new direction(dr, dc)after a 90-degree clockwise turn. ii. Initializelen2 = 0,currentIndex = len1,currR = r,currC = c. iii. Loop: Move to(currR + dr, currC + dc). If it's in bounds and the value matchesgetExpectedValue(currentIndex), incrementlen2andcurrentIndex, and update(currR, currC). Otherwise, break. iv. UpdatemaxLength = max(maxLength, len1 + len2).
- Iterate through each cell
- Return
maxLength.
Walkthrough
The core idea is to break down the problem into two main parts: finding all valid straight segments and then combining them to form V-shapes.
-
Pre-computation of Straight Segments: We use four 2D DP arrays, one for each of the four diagonal directions (Top-Left to Bottom-Right, Top-Right to Bottom-Left, etc.). Let's denote them
L_tl,L_tr,L_bl,L_br.L_tl[r][c]will store the length of a valid straight diagonal segment ending at cell(r, c)and arriving from the top-left.The calculation is as follows: To compute
L_tl[r][c], we look at the previous cell in that diagonal,(r-1, c-1). If a valid segment of lengthkends there (i.e.,L_tl[r-1][c-1] = k > 0), and the value atgrid[r][c]matches the expected value at indexkof the sequence (1, 2, 0, 2, 0, ...), then we can extend the segment. The new length at(r, c)becomesk + 1. Ifgrid[r][c]is1, it can start a new segment of length 1. Otherwise, no valid segment ends at(r, c)from this direction.We fill these four DP tables by iterating through the grid in appropriate orders. While filling, we also keep track of the maximum length found so far, which covers all straight-line segments (V-shapes with zero turns).
-
Finding V-Shapes: After the DP tables are filled, we iterate through every cell
(r, c)in the grid, treating it as a potential pivot point of a V-shape. For each of the four possible incoming diagonal directions, we get the length of the first leg from our pre-computed DP tables (e.g.,len1 = L_tl[r][c]).If a valid first leg exists (
len1 > 0), we then simulate the second leg. A 90-degree clockwise turn from the incoming direction determines the direction of the second leg. We then iteratively traverse from(r, c)in this new direction, checking if the grid values match the required sequence, which now continues from indexlen1. The length of this second leg (len2) is calculated. The total length of the V-shape islen1 + len2. We update our global maximum length with this value.
This process is repeated for all cells and all four possible turns at each cell.
Complexity
Time
O(n * m * (n + m)). The pre-computation of the four DP tables takes O(n * m) time. The main cost comes from the V-shape calculation, where we iterate through each of the n*m cells. At each cell, we potentially start an iterative search for the second leg, which can take up to O(n + m) time in the worst case.
Space
O(n * m) to store the four DP tables for the lengths of straight segments.
Trade-offs
Pros
Much more efficient than a naive brute-force approach.
Systematically explores all possibilities without redundant calculations of the first leg of the V-shape.
Cons
The second leg of the V-shape is calculated iteratively for each potential turning point, leading to repeated traversals over the same cells.
The time complexity can be prohibitive for very large grids, although it might pass for the given constraints.
This is the most efficient approach, which uses dynamic programming to pre-calculate the lengths of all possible segments, both for the first and second legs of a V-shape. By investing in a more comprehensive pre-computation phase, we can find the length of the longest V-shape by simply combining the pre-calculated values in constant time for each potential turning point, thus avoiding any iterative traversals during the final combination step.
Algorithm
- Initialize
maxLength = 0, grid dimensionsn,m. - Define direction vectors
dr,dcfor the four diagonal directions. - Create DP tables:
L[n][m][4]: For first legs (sequence1, 2, 0, ...).S[n][m][4]: For second legs starting with2(2, 0, 2, ...).T[n][m][4]: For second legs starting with0(0, 2, 0, ...).
- Compute
Ltables:- Iterate through the grid (e.g., top-to-bottom, left-to-right for directions from top) and fill
Ltables. UpdatemaxLengthwith eachLvalue.
- Iterate through the grid (e.g., top-to-bottom, left-to-right for directions from top) and fill
- Compute
SandTtables:- Iterate through the grid in reverse orders (e.g., bottom-to-top, right-to-left for directions towards bottom-right) and fill
SandTtables based on their recursive definitions.
- Iterate through the grid in reverse orders (e.g., bottom-to-top, right-to-left for directions towards bottom-right) and fill
- Combine for V-shapes:
- Iterate
rfrom0ton-1andcfrom0tom-1. - For each incoming direction
d_infrom0to3: a.len1 = L[r][c][d_in]. b. Iflen1 > 0: i.d_out = (d_in + 1) % 4(clockwise turn). ii.nextR = r + dr[d_out],nextC = c + dc[d_out]. iii. If(nextR, nextC)is in bounds: -expected = (len1 % 2 == 1) ? 2 : 0. - Ifgrid[nextR][nextC] == expected: -len2 = (expected == 2) ? S[nextR][nextC][d_out] : T[nextR][nextC][d_out]. -maxLength = max(maxLength, len1 + len2).
- Iterate
- Return
maxLength.
Walkthrough
This approach extends the previous one by eliminating the iterative search for the second leg of the V-shape. It does so by pre-calculating the lengths of all possible second legs as well.
We define three sets of DP tables:
-
L[r][c][dir]: Stores the length of a valid segment starting with1(1, 2, 0, ...sequence) that ends at(r, c), arriving from directiondir. This is identical to the DP tables in the previous approach and represents the first leg of a V-shape. -
S[r][c][dir]: Stores the length of a valid segment that starts at(r, c)with the value2and continues with the sequence0, 2, 0, ...along directiondir. -
T[r][c][dir]: Stores the length of a valid segment that starts at(r, c)with the value0and continues with the sequence2, 0, 2, ...along directiondir.
The S and T tables are mutually dependent. For example, to calculate S for a direction (e.g., towards bottom-right), S_br[r][c] will be 1 + T_br[r+1][c+1] if grid[r][c] is 2, and 0 otherwise. Similarly, T_br[r][c] depends on S_br at the next cell. These tables can be filled by iterating through the grid in the reverse order of the direction of traversal.
The Algorithm:
-
Pre-computation:
- First, compute the four
Ltables, one for each incoming direction, just like in the previous approach. While doing so, update amaxLengthvariable to account for all straight-line segments. - Next, compute the
SandTtables. For each of the four diagonal directions, we need oneSand oneTtable (total of 8 tables). These are computed by iterating in the reverse direction (e.g., for segments going towards the bottom-right, we iterate from the bottom-right of the grid backwards).
- First, compute the four
-
Combination:
- Iterate through every cell
(r, c)of the grid, considering it as the pivot of a V-shape. - For each of the four possible incoming directions
d_in: a. Get the length of the first leg:len1 = L[r][c][d_in]. b. Iflen1 > 0, it means a valid first leg ends at(r, c). c. The second leg starts at the cell adjacent to(r, c)in the turned directiond_out. The expected value at this next cell depends onlen1. Iflen1is odd, the next value should be2; if even, it should be0. d. We check if the value at the next cell matches the expectation. If it does, we can find the length of the rest of the second leg (len2) inO(1)time by looking it up in the pre-computedSorTtables for directiond_outat that next cell's coordinates. e. The total length islen1 + len2. We updatemaxLengthwith this combined length.
- Iterate through every cell
After checking all cells as potential pivots, maxLength will hold the length of the longest V-shaped segment.
Complexity
Time
O(n * m). Each of the 12 DP tables is computed in O(n * m) time. The final combination step also takes O(n * m) time as it involves a simple lookup for each cell and direction. The total time complexity is dominated by these linear scans of the grid.
Space
O(n * m). We use 12 DP tables, each of size n x m. The space required is therefore proportional to the size of the grid.
Trade-offs
Pros
Optimal time complexity.
Each phase of the algorithm (pre-computation, combination) is clean and efficient.
Avoids all redundant computations by leveraging DP tables for all segment types.
Cons
Requires significant memory to store 12 DP tables, which might be an issue for extremely large grids, though acceptable for the given constraints.
The implementation is more complex due to the need to manage multiple DP tables and different traversal orders.
Solutions
Solution
class Solution: def lenOfVDiagonal(self, grid: List[List[int]]) -> int: m, n = len(grid), len(grid[0]) next_digit = {1: 2, 2: 0, 0: 2} def within_bounds(i, j): return 0 <= i < m and 0 <= j < n @ cache def f(i, j, di, dj, turned): result = 1 successor = next_digit[grid[i][j]] if within_bounds(i + di, j + dj) and grid[i + di][j + dj] == successor: result = 1 + f(i + di, j + dj, di, dj, turned) if not turned: di, dj = dj, - di if within_bounds(i + di, j + dj) and grid[i + di][j + dj] == successor: result = max(result, 1 + f(i + di, j + dj, di, dj, True)) return result directions = ((1, 1), (- 1, 1), (1, - 1), (- 1, - 1)) result = 0 for i in range(m): for j in range(n): if grid[i][j] != 1: continue for di, dj in directions: result = max(result, f(i, j, di, dj, False)) return resultVideo walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.