Facebook Pixel

3417. Zigzag Grid Traversal With Skip

EasyArrayMatrixSimulation
Leetcode Link

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:

  1. 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.

  2. 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 to False after visiting every cell and back to True again). Only append the value to the results list when the boolean is True.

  3. 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:

  1. Initial Setup:

    • Create a boolean variable ok initialized to True. 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.
  2. Iterate Over Each Row:

    • Use a loop to iterate over each row in the grid, indexed by i.
    • If i is odd, reverse the elements of the current row using row.reverse(). This reversal ensures that the traversal is in the opposite direction (left-to-right for odd-indexed rows).
  3. Process Each Cell in the Row:

    • For each element x in the row, check the value of ok.
    • If ok is True, append the element to the ans 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.
  4. 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.

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 Evaluator

Example 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.

  1. Initial Setup:

    • Initialize a boolean variable ok to True.
    • Create an empty list ans to store visited cells' values.
  2. 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, add 1 to ans, toggle ok.
        • Cell 2: ok = False, skip 2, toggle ok.
        • Cell 3: ok = True, add 3 to ans, toggle ok.
      • 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, skip 6, toggle ok.
        • Cell 5: ok = True, add 5 to ans, toggle ok.
        • Cell 4: ok = False, skip 4, toggle ok.
      • The result from the second row is [5].

    • Third Row (i = 2):

      • Traverse right: [7, 8, 9].

      • Traversing:

        • Cell 7: ok = True, add 7 to ans, toggle ok.
        • Cell 8: ok = False, skip 8, toggle ok.
        • Cell 9: ok = True, add 9 to ans, toggle ok.
      • The result from the third row is [7, 9].

  3. Combine the Results:

    • Resulting traversal path: [1, 3, 5, 7, 9].

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.


Discover Your Strengths and Weaknesses: Take Our 2-Minute Quiz to Tailor Your Study Plan:
Question 1 out of 10

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

Want a Structured Path to Master System Design Too? Don’t Miss This!


Load More