Zigzag Grid Traversal With Skip
EasyPrompt
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.
Zigzag pattern traversal is defined as following the below actions:
- Start at the top-left cell
(0, 0). - Move right within a row until the end of the row is reached.
- Drop down to the next row, then traverse left until the beginning of the row is reached.
- Continue alternating between right and left traversal until every row has been traversed.
Note that you must skip every alternate cell during the traversal.
Return an array of integers result containing, in order, the value of the cells visited during the zigzag traversal with skips.
Example 1:
Input: grid = [[1,2],[3,4]]
Output: [1,4]
Explanation:

Example 2:
Input: grid = [[2,1],[2,1],[2,1]]
Output: [2,1,2]
Explanation:

Example 3:
Input: grid = [[1,2,3],[4,5,6],[7,8,9]]
Output: [1,3,5,7,9]
Explanation:

Constraints:
2 <= n == grid.length <= 502 <= m == grid[i].length <= 501 <= grid[i][j] <= 2500
Approaches
2 approaches with complexity analysis and trade-offs.
This approach breaks the problem into two distinct steps. First, it traverses the entire grid in the specified zigzag pattern and stores all the cell values in an intermediate list. This creates a linear sequence of all numbers as they would be encountered. In the second step, it iterates through this intermediate list and picks every alternate element (the first, third, fifth, etc.) to build the final result.
Algorithm
- Initialize an empty
ArrayList<Integer>calledzigzagOrder. - Get the grid dimensions,
rowsandcols. - Iterate through each row of the grid from
i = 0torows - 1. - If the row index
iis even, traverse the columns from left to right (j = 0tocols - 1) and addgrid[i][j]tozigzagOrder. - If the row index
iis odd, traverse the columns from right to left (j = cols - 1down to0) and addgrid[i][j]tozigzagOrder. - After the first traversal is complete, initialize another empty
ArrayList<Integer>calledresult. - Iterate through the
zigzagOrderlist with an indexk, incrementing by 2 in each step (k = 0, 2, 4, ...). - In each step, add the element
zigzagOrder.get(k)to theresultlist. - Return the
resultlist.
Walkthrough
This method first linearizes the 2D grid into a 1D list according to the zigzag traversal rule. Once this complete sequence is stored, a second pass is made over the new list to select every other element, effectively applying the skipping rule.
import java.util.ArrayList;import java.util.List; class Solution { public List<Integer> zigzagTraversal(int[][] grid) { int rows = grid.length; int cols = grid[0].length; List<Integer> zigzagOrder = new ArrayList<>(); // First pass: Create a list of all elements in zigzag order for (int i = 0; i < rows; i++) { if (i % 2 == 0) { // Even row: traverse left to right for (int j = 0; j < cols; j++) { zigzagOrder.add(grid[i][j]); } } else { // Odd row: traverse right to left for (int j = cols - 1; j >= 0; j--) { zigzagOrder.add(grid[i][j]); } } } // Second pass: Pick every alternate element List<Integer> result = new ArrayList<>(); for (int k = 0; k < zigzagOrder.size(); k += 2) { result.add(zigzagOrder.get(k)); } return result; }}Complexity
Time
O(rows * cols). The first pass to populate `zigzagOrder` takes O(rows * cols) time as it visits every cell. The second pass to populate `result` also takes O(rows * cols) time. The total time is O(rows * cols) + O(rows * cols) = O(rows * cols).
Space
O(rows * cols). An intermediate list `zigzagOrder` is created to store all `rows * cols` elements of the grid. The `result` list also stores up to `ceil((rows * cols) / 2)` elements. Thus, the space complexity is dominated by the intermediate list.
Trade-offs
Pros
Conceptually simple, as it separates the traversal logic from the skipping logic.
Cons
Requires significant extra memory to store the intermediate list of all grid elements.
Less efficient than a single-pass solution due to iterating over the data twice and higher memory allocation overhead.
This is the most efficient approach. It simulates the zigzag traversal and makes the decision to add an element to the result list on the fly. A single boolean flag is used to keep track of whether the current cell is an 'add' or 'skip' cell in the overall traversal sequence. This avoids the need for an intermediate data structure and completes the task in a single pass over the grid.
Algorithm
- Initialize an empty
ArrayList<Integer>calledresult. - Initialize a boolean flag,
shouldAdd, totrue. - Get the grid dimensions,
rowsandcols. - Iterate through each row of the grid from
i = 0torows - 1. - Check the row index
ito determine the direction of traversal. - If
iis even: Traverse columns from left to right (j = 0tocols - 1). - If
iis odd: Traverse columns from right to left (j = cols - 1down to0). - For each cell encountered in the traversal:
- If
shouldAddistrue, add the cell's value toresult. - Toggle the flag:
shouldAdd = !shouldAdd.
- If
- After iterating through all cells, return the
resultlist.
Walkthrough
This optimal solution performs the zigzag traversal and the skipping logic simultaneously. It maintains a state (a boolean flag shouldAdd) that tracks the overall position in the traversal (1st, 2nd, 3rd, etc.). This flag is toggled for every cell visited in the zigzag path, and the cell's value is added to the result only when the flag is true. This eliminates the need for extra space for an intermediate list.
import java.util.ArrayList;import java.util.List; class Solution { public List<Integer> zigzagTraversal(int[][] grid) { int rows = grid.length; int cols = grid[0].length; List<Integer> result = new ArrayList<>(); boolean shouldAdd = true; for (int i = 0; i < rows; i++) { if (i % 2 == 0) { // Even row: traverse left to right for (int j = 0; j < cols; j++) { if (shouldAdd) { result.add(grid[i][j]); } shouldAdd = !shouldAdd; } } else { // Odd row: traverse right to left for (int j = cols - 1; j >= 0; j--) { if (shouldAdd) { result.add(grid[i][j]); } shouldAdd = !shouldAdd; } } } return result; }}Complexity
Time
O(rows * cols). We iterate through each of the `rows * cols` cells in the grid exactly once. All operations inside the loops are constant time.
Space
O(rows * cols) or O(1). The space required for the output `result` list is O(rows * cols), as it can contain up to `ceil((rows * cols) / 2)` elements. If the output list is not considered as extra space, the space complexity is O(1) as we only use a few variables (`i`, `j`, `shouldAdd`) to perform the traversal.
Trade-offs
Pros
Highly efficient in both time and space.
Processes the grid in a single pass.
Requires minimal auxiliary space (excluding the output list).
Cons
The logic for traversal and skipping is intertwined, which might be slightly less straightforward to read for a beginner compared to the two-pass approach.
Solutions
Solution
class Solution {public List<Integer> zigzagTraversal(int[][] grid) { boolean ok = true; List<Integer> ans = new ArrayList<>(); for (int i = 0; i < grid.length; ++i) { if (i % 2 == 1) { reverse(grid[i]); } for (int x : grid[i]) { if (ok) { ans.add(x); } ok = !ok; } } return ans; }private void reverse(int[] nums) { for (int i = 0, j = nums.length - 1; i < j; ++i, --j) { int t = nums[i]; nums[i] = nums[j]; nums[j] = t; } }}class Solution {public: vector<int> zigzagTraversal(vector<vector<int>> &grid) { vector<int> ans; bool ok = true; for (int i = 0; i < grid.size(); ++i) { if (i % 2 != 0) { ranges ::reverse(grid[i]); } for (int x : grid[i]) { if (ok) { ans.push_back(x); } ok = !ok; } } return ans; }};class Solution: def zigzagTraversal(self, grid: List[List[int]]) -> List[int]: ok = True ans = [] for i, row in enumerate(grid): if i % 2: row . reverse() for x in row: if ok: ans . append(x) ok = not ok return ansVideo 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.