3417. Zigzag Grid Traversal With Skip
Problem Description
You are given an m x n
2D array grid
of positive integers. Your task is to traverse grid
in a zigzag pattern while skipping every alternate cell. The zigzag pattern is defined with the following steps:
- Start at the top-left cell
(0, 0)
. - Move right within a row until you reach the end of the row.
- Drop down to the next row, then traverse left until you reach the beginning of that row.
- Continue alternating between right and left traversal until each row has been traversed.
Important to note that every alternate cell is skipped during the traversal. Return an array of integers result
containing, in order, the value of the cells visited during this zigzag traversal with skips.
Intuition
The key to solving this problem lies in understanding the zigzag traversal pattern across the grid. We can break down the solution using the following intuitive approach:
-
Alternating Row Traversal: Recognize that for a zigzag traversal, we need to alternate row-by-row. Going right on even-indexed rows and left on odd-indexed rows creates the zigzag pattern. This can be achieved by reversing the elements of the odd-indexed rows.
-
Alternate Cell Skipping: It is also necessary to skip every alternate cell during the traversal. This is achieved by maintaining a toggle or a boolean switch. Start with a boolean set to
True
, and toggle its value (i.e., switch it toFalse
after visiting every cell and back toTrue
again). Only append the value to the results list when the boolean isTrue
. -
Implementation: Traverse through the grid row by row. Reverse rows as needed (specifically those with an odd index) to implement the zigzag pattern dynamically. Use the boolean toggle to selectively append the appropriate values to the output list.
These steps combine to provide a clean and direct traversal approach that aligns with the problem constraints and requirements.
Solution Approach
The implementation of the zigzag traversal solution uses a straightforward simulation approach. Here’s a detailed walkthrough of the solution algorithm:
-
Initial Setup:
- Create a boolean variable
ok
initialized toTrue
. This will help in determining whether to visit (append) a cell or skip it, adhering to the requirement of skipping every alternate cell. - An empty list
ans
is initialized to collect the values of the visited cells.
- Create a boolean variable
-
Iterate Over Each Row:
- Use a loop to iterate over each row in the
grid
, indexed byi
. - If
i
is odd, reverse the elements of the current row usingrow.reverse()
. This reversal ensures that the traversal is in the opposite direction (left-to-right for odd-indexed rows).
- Use a loop to iterate over each row in the
-
Process Each Cell in the Row:
- For each element
x
in therow
, check the value ofok
. - If
ok
isTrue
, append the element to theans
list, indicating this cell is part of the zigzag path. - Toggle the boolean
ok
to switch its state after each cell is processed, allowing alternate cells to be skipped.
- For each element
-
Return the Result:
- Once all rows have been processed, the list
ans
which contains the values of cells visited in zigzag order with skips is returned as the final result.
- Once all rows have been processed, the list
The core pattern here is iterating over the entire 2D grid, alternating directions via row reversal and strategically appending elements based on the toggling boolean to establish skipping. This solution approach efficiently handles the problem requirements by combining these logical operations with basic data structure manipulations.
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 consider a small example grid
to illustrate the solution approach. Suppose the grid
is given by:
grid = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]
We aim to traverse this grid
in a zigzag manner while skipping every alternate cell.
-
Initial Setup:
- Initialize a boolean variable
ok
toTrue
. - Create an empty list
ans
to store visited cells' values.
- Initialize a boolean variable
-
Process Each Row:
-
First Row (
i = 0
):-
The top-left starting point is
(0, 0)
, i.e.,1
. -
Traverse to the right:
[1, 2, 3]
. -
Traversing:
- Cell
1
:ok = True
, add1
toans
, toggleok
. - Cell
2
:ok = False
, skip2
, toggleok
. - Cell
3
:ok = True
, add3
toans
, toggleok
.
- Cell
-
The result from the first row is
[1, 3]
.
-
-
Second Row (
i = 1
):-
Reverse direction (traverse left):
[6, 5, 4]
. -
Traversing:
- Cell
6
:ok = False
, skip6
, toggleok
. - Cell
5
:ok = True
, add5
toans
, toggleok
. - Cell
4
:ok = False
, skip4
, toggleok
.
- Cell
-
The result from the second row is
[5]
.
-
-
Third Row (
i = 2
):-
Traverse right:
[7, 8, 9]
. -
Traversing:
- Cell
7
:ok = True
, add7
toans
, toggleok
. - Cell
8
:ok = False
, skip8
, toggleok
. - Cell
9
:ok = True
, add9
toans
, toggleok
.
- Cell
-
The result from the third row is
[7, 9]
.
-
-
-
Combine the Results:
- Resulting traversal path:
[1, 3, 5, 7, 9]
.
- Resulting traversal path:
Thus, the final result
array produced by visiting the zigzag pattern with skips is [1, 3, 5, 7, 9]
.
Solution Implementation
1from typing import List
2
3class Solution:
4 def zigzagTraversal(self, grid: List[List[int]]) -> List[int]:
5 # Flag to determine whether to add the current element
6 ok = True
7 # List to store the result of the zigzag traversal
8 ans = []
9
10 # Iterate over each row in the grid, with index
11 for i, row in enumerate(grid):
12 # Reverse the row if it is an odd-numbered row (1-indexed perspective)
13 if i % 2 == 1:
14 row.reverse()
15
16 # Traverse through each element in the possibly reversed row
17 for x in row:
18 # Add the element to the result list only if 'ok' is True
19 if ok:
20 ans.append(x)
21 # Toggle the value of 'ok' for alternate additions
22 ok = not ok
23
24 return ans
25
1import java.util.ArrayList;
2import java.util.List;
3
4class Solution {
5 // Main method that performs zigzag traversal on a 2D grid
6 public List<Integer> zigzagTraversal(int[][] grid) {
7 // Flag to determine whether to add the current element to the result
8 boolean shouldAdd = true;
9 // Result list to store the zigzag order of elements
10 List<Integer> result = new ArrayList<>();
11
12 // Iterate over each row in the grid
13 for (int i = 0; i < grid.length; ++i) {
14 // If the row index is odd, reverse the current row
15 if (i % 2 == 1) {
16 reverse(grid[i]);
17 }
18
19 // Iterate over each element in the current row
20 for (int element : grid[i]) {
21 // Add the element to the result list if the flag is true
22 if (shouldAdd) {
23 result.add(element);
24 }
25 // Toggle the flag after each element
26 shouldAdd = !shouldAdd;
27 }
28 }
29 // Return the final zigzag order of elements
30 return result;
31 }
32
33 // Helper method to reverse an array in place
34 private void reverse(int[] nums) {
35 int start = 0;
36 int end = nums.length - 1;
37
38 // Swap elements from start to end until the middle of the array is reached
39 while (start < end) {
40 int temp = nums[start];
41 nums[start] = nums[end];
42 nums[end] = temp;
43 start++;
44 end--;
45 }
46 }
47}
48
1class Solution {
2public:
3 std::vector<int> zigzagTraversal(std::vector<std::vector<int>>& grid) {
4 std::vector<int> result; // This will store the result of the zigzag traversal
5 bool includeElement = true; // Control flag to alternate addition of elements
6
7 // Iterate through each row of the grid
8 for (size_t row = 0; row < grid.size(); ++row) {
9 // Reverse the order of elements in the row if the row index is odd
10 if (row % 2 != 0) {
11 std::reverse(grid[row].begin(), grid[row].end());
12 }
13
14 // Traverse the current row
15 for (int element : grid[row]) {
16 // If flag allows, add the element to the result
17 if (includeElement) {
18 result.push_back(element);
19 }
20 // Toggle the flag to alternate inclusion
21 includeElement = !includeElement;
22 }
23 }
24 return result;
25 }
26};
27
1function zigzagTraversal(grid: number[][]): number[] {
2 // Initialize an array to store the result
3 const ans: number[] = [];
4 // This variable will toggle to control whether to append an element or not
5 let ok: boolean = true;
6
7 // Iterate through each row of the grid
8 for (let i = 0; i < grid.length; ++i) {
9 // If the current row index is odd, reverse the row
10 if (i % 2) {
11 grid[i].reverse();
12 }
13
14 // Iterate through elements in the current row
15 for (const x of grid[i]) {
16 // Check the value of 'ok' to decide whether to push the element
17 if (ok) {
18 ans.push(x);
19 }
20 // Toggle the 'ok' flag
21 ok = !ok;
22 }
23 }
24
25 // Return the zigzag traversed result
26 return ans;
27}
28
Time and Space Complexity
The time complexity of the given code is O(m \times n)
, where m
is the number of rows and n
is the number of columns in the 2D array grid
. This is because the code iterates over each element of the grid exactly once, either to append it to the ans
list or to toggle the ok
flag after checking the condition.
The space complexity, disregarding the space used for the output list ans
, is O(1)
. This is because the code uses a constant amount of additional space for variables such as ok
, i
, row
, and x
, regardless of the size of the grid.
Learn more about how to find time and space complexity quickly.
What is the best way of checking if an element exists in an unsorted array once in terms of time complexity? Select the best that applies.
Recommended Readings
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
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https algomonster s3 us east 2 amazonaws com recursion jpg You first
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!