> ## Documentation Index
> Fetch the complete documentation index at: https://leetcode-py.wisl.dev/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> leetcode-py is a Python LeetCode practice environment generator with one CLI: lcpy. It is not a service or platform.
> Each problem is a directory under leetcode/ with README.md, solution.py, test_solution.py, helpers.py, and playground.ipynb. lcpy gen creates them from JSON templates bundled with the package.
> Examples are backed by tests; copy them verbatim.

# Zigzag Iterator Python Solution with Tests

> Tested Python solution for LeetCode 281 with 13 pytest cases. Generate a practice environment with lcpy.

LeetCode 281, [Medium](/catalog/medium). Topics: [Design](/catalog/topics/design), [Queue](/catalog/topics/queue), [Array](/catalog/topics/array), Iterator. [View on LeetCode](https://leetcode.com/problems/zigzag-iterator/description/).

Generate this problem as a practice environment: tested reference solution, 13 [parametrized pytest cases](/practice/testing), and a playground notebook:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
lcpy gen -n 281   # by problem number
lcpy gen -s zigzag_iterator   # by problem name
```

## Problem

Given two vectors of integers `v1` and `v2`, implement an iterator to return their elements alternately.

Implement the `ZigzagIterator` class:

* `ZigzagIterator(List<int> v1, List<int> v2)` initializes the object with the two vectors `v1` and `v2`.
* `boolean hasNext()` returns `true` if the iterator still has elements, and `false` otherwise.
* `int next()` returns the current element of the iterator and moves the iterator to the next element.

**Follow up:** What if you are given `k` vectors? How well can your code be extended to such cases?

### Examples

```
Input: v1 = [1,2], v2 = [3,4,5,6]
Output: [1,3,2,4,5,6]
Explanation: By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,3,2,4,5,6].
```

```
Input: v1 = [1], v2 = []
Output: [1]
```

```
Input: v1 = [], v2 = [1]
Output: [1]
```

### Constraints

* `0 <= v1.length, v2.length <= 1000`
* `1 <= v1.length + v2.length <= 2000`
* `-10^9 <= v1[i], v2[i] <= 10^9`

## Solution

Reference implementation from [solution.py on GitHub](https://github.com/wislertt/leetcode-py/blob/main/leetcode/zigzag_iterator/solution.py), full suite in [test\_solution.py](https://github.com/wislertt/leetcode-py/blob/main/leetcode/zigzag_iterator/test_solution.py):

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from collections import deque


class ZigzagIterator:
    # Time: O(1) per call
    # Space: O(v1.length + v2.length)
    def __init__(self, v1: list[int], v2: list[int]) -> None:
        self._queues: list[deque[int]] = [deque(v) for v in (v1, v2) if v]
        self._turn = 0

    def _prune_empty(self) -> None:
        self._queues = [queue for queue in self._queues if queue]
        if self._turn >= len(self._queues):
            self._turn = 0

    # Time: O(1) amortized
    # Space: O(1)
    def next(self) -> int:
        self._prune_empty()
        queue = self._queues[self._turn]
        value = queue.popleft()
        if self._queues:
            self._turn = (self._turn + 1) % len(self._queues)
        return value

    # Time: O(1)
    # Space: O(1)
    def has_next(self) -> bool:
        self._prune_empty()
        return bool(self._queues)
```

## Complexity

| Time | Space |
| - | - |
| O(1) per call | O(v1.length + v2.length) |

## Tags

[NeetCode All](/catalog/neetcode).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.