πΉ Problem: 3459. Length of Longest V-Shaped Diagonal Segment
Difficulty: Hard
Tags: #DynamicProgramming #Grid #DFS
π Problem Summary
You are given a binary grid (
0
s and1
s).
A V-shaped diagonal segment is defined as a path that:
- Starts at a cell with value
1
.- Moves diagonally in one of the four directions (β, β, β, β).
- At some point, turns exactly once clockwise (90Β°).
- Alternates values along the path (
1 β 2 β 1 β 2 β¦
).The task is to find the maximum length of such a segment.
π§ My Thought Process
-
Brute Force Idea:
- From every
1
cell, try walking diagonally in all directions. - Keep track of visited cells and attempt to form a V-shape.
- This would be exponential because at each step, you can choose to continue straight or turn β too slow.
- From every
-
Optimized Strategy:
- Notice that the segment is strictly alternating (
1-2-1-2β¦
). - We only need to know:
- Current position
(x, y)
. - Current direction (which diagonal weβre going).
- Whether weβve already turned (boolean).
- What value we expect next (
1
or2
). - This screams DFS + Memoization (cache).
- Notice that the segment is strictly alternating (
-
Key Insight:
- If we move straight β continue the same direction.
- If we havenβt turned yet β try turning clockwise and continue.
- Use
@cache
so we donβt recompute states.
βοΈ Algorithm (Step-by-Step)
- Define 4 diagonal directions:
-
β (1,1)
,β (1,-1)
,β (-1,-1)
,β (-1,1)
.
- Write a recursive DFS function with memoization:
- Input:
(x, y, direction, can_turn, expected_value)
. - Compute next
(nx, ny)
in the same direction. - If out of bounds or value β expected β stop.
-
Otherwise:
- Continue straight in same direction.
- If
can_turn = True
, try turning clockwise and recurse.
Add
+1
at each successful step.From every
1
in the grid, try all 4 directions with initialcan_turn=True
, expecting2
next.Keep global maximum.
βοΈ Code Implementation (Python)
from functools import cache
from typing import List
class Solution:
def lenOfVDiagonal(self, grid: List[List[int]]) -> int:
DIRS = [(1, 1), (1, -1), (-1, -1), (-1, 1)] # diagonals
m, n = len(grid), len(grid[0])
@cache
def dfs(x, y, d, can_turn, target):
nx, ny = x + DIRS[d][0], y + DIRS[d][1]
if nx < 0 or ny < 0 or nx >= m or ny >= n or grid[nx][ny] != target:
return 0
best = dfs(nx, ny, d, can_turn, 3 - target) # continue straight
if can_turn:
best = max(best, dfs(nx, ny, (d + 1) % 4, False, 3 - target)) # turn
return best + 1
res = 0
for i in range(m):
for j in range(n):
if grid[i][j] == 1: # must start from 1
for d in range(4):
res = max(res, dfs(i, j, d, True, 2) + 1)
return res
β±οΈ Time & Space Complexity
Time:
Each state(x, y, direction, can_turn, target)
is computed once β
O(m Γ n Γ 4 Γ 2 Γ 2) β O(mn).-
Space:
- Memoization cache β
O(mn)
states. - DFS recursion stack depth at most
O(m+n)
.
- Memoization cache β
π§© Key Takeaways
- β Converted brute force into stateful DFS + memoization.
- π‘ Trick: No need to calculate actual diagonals β just use
(dx,dy)
pairs. - π Similar problems will involve grid + path + direction + turn state β DP over state space.
π Reflection (Self-Check)
- [ ] Could I solve this without help? -> This problem had a lot of moving parts for me to handle alone.
- [x] Did I understand why memoization was necessary?
- [x] Did I capture the turning logic correctly?
- [ ] Can I implement this again tomorrow without notes?
π Progress Tracker
Metric | Value |
---|---|
Day | 68 |
Total Problems Solved | 430 |
Confidence Today | π |
Leetcode Rating | 1530 |
Top comments (0)