Article / 文章

LeetCode 第281题:锯齿迭代器

给出两个一维向量,请你实现一个迭代器来交替返回它们中间的元素。 实现 ZigzagIterator 类: - ZigzagIterator(vector& v1, vector& v2) 使用两个向量v1和v2初始化迭代器 - boolean hasNext() 如果还有元素返回 true ;否则返回 false 。 - int next() 返回下一个元素

📖 文章摘要

本文详细解析LeetCode第281题“锯齿迭代器”,这是一道考察迭代器设计的中等难度题目。文章提供了队列和指针两种实现方案,包含C#、Python、C++三种语言实现,配有详细的迭代过程分析表格和性能对比。适合学习迭代器设计和数据结构的读者。

核心知识点: 迭代器设计、队列、指针操作
难度等级: 中等
推荐人群: 具备基础数据结构知识,想要提升迭代器设计能力的开发者

题目描述

给出两个一维向量,请你实现一个迭代器来交替返回它们中间的元素。

实现 ZigzagIterator 类:

  • ZigzagIterator(vector<int>& v1, vector<int>& v2) 使用两个向量v1和v2初始化迭代器
  • boolean hasNext() 如果还有元素返回 true ;否则返回 false
  • int next() 返回下一个元素。如果没有下一个元素,返回 -1

示例

示例 1:

输入:v1 = [1,2], v2 = [3,4,5,6]
输出:[1,3,2,4,5,6]
解释:通过迭代器依次返回:1,3,2,4,5,6

示例 2:

输入:v1 = [1], v2 = []
输出:[1]

示例 3:

输入:v1 = [], v2 = [1]
输出:[1]

提示

  • 0 <= v1.length, v2.length <= 1000
  • 1 <= v1.length + v2.length <= 2000
  • -2^31 <= v1[i], v2[i] <= 2^31 - 1

解题思路

本题可以使用两种方法来实现:

  1. 队列方法:

    • 使用队列存储每个向量的迭代器
    • 每次从队列头取出一个迭代器获取元素
    • 如果该迭代器还有下一个元素,将其重新加入队列尾部
  2. 指针方法:

    • 维护两个指针分别指向两个向量的当前位置
    • 使用一个标志位记录当前应该返回哪个向量的元素
    • 每次返回元素后更新相应的指针和标志位

图解思路

队列方法迭代过程分析表

步骤 队列状态 返回值 v1指针 v2指针 说明
初始 [v1,v2] - 0 0 两个向量的迭代器入队
1 [v2,v1] 1 1 0 取v1元素,v1还有元素,重新入队
2 [v1,v2] 3 1 1 取v2元素,v2还有元素,重新入队
3 [v2,v1] 2 2 1 取v1元素,v1无元素,不再入队
4 [v2] 4 2 2 取v2元素,v2还有元素,重新入队
5 [v2] 5 2 3 取v2元素,v2还有元素,重新入队
6 [v2] 6 2 4 取v2元素,v2无元素,队列为空

指针方法状态分析表

当前标志 v1指针 v2指针 返回值 下一标志 说明
1 0 0 1 2 返回v1元素,切换到v2
2 1 0 3 1 返回v2元素,切换到v1
1 1 1 2 2 返回v1元素,切换到v2
2 2 1 4 2 返回v2元素,v1已空,继续v2
2 2 2 5 2 返回v2元素,继续v2
2 2 3 6 - 返回v2最后元素

代码实现

C# 实现

public class ZigzagIterator {
    private Queue<(List<int>, int)> queue;
    
    public ZigzagIterator(IList<int> v1, IList<int> v2) {
        queue = new Queue<(List<int>, int)>();
        if (v1.Count > 0)
            queue.Enqueue((v1.ToList(), 0));
        if (v2.Count > 0)
            queue.Enqueue((v2.ToList(), 0));
    }

    public bool HasNext() {
        return queue.Count > 0;
    }

    public int Next() {
        if (!HasNext()) return -1;
        
        var (list, index) = queue.Dequeue();
        int result = list[index];
        
        if (index + 1 < list.Count)
            queue.Enqueue((list, index + 1));
            
        return result;
    }
}

Python 实现

class ZigzagIterator:
    def __init__(self, v1: List[int], v2: List[int]):
        self.queue = collections.deque()
        if v1:
            self.queue.append((v1, 0))
        if v2:
            self.queue.append((v2, 0))

    def next(self) -> int:
        if not self.hasNext():
            return -1
            
        vec, index = self.queue.popleft()
        result = vec[index]
        
        if index + 1 < len(vec):
            self.queue.append((vec, index + 1))
            
        return result

    def hasNext(self) -> bool:
        return len(self.queue) > 0

C++ 实现

class ZigzagIterator {
private:
    queue<pair<vector<int>, int>> q;
    
public:
    ZigzagIterator(vector<int>& v1, vector<int>& v2) {
        if (!v1.empty())
            q.push({v1, 0});
        if (!v2.empty())
            q.push({v2, 0});
    }

    int next() {
        if (!hasNext()) return -1;
        
        auto [vec, index] = q.front();
        q.pop();
        int result = vec[index];
        
        if (index + 1 < vec.size())
            q.push({vec, index + 1});
            
        return result;
    }

    bool hasNext() {
        return !q.empty();
    }
};

执行结果

C# 实现

  • 执行用时:92 ms
  • 内存消耗:25.8 MB

Python 实现

  • 执行用时:36 ms
  • 内存消耗:15.1 MB

C++ 实现

  • 执行用时:4 ms
  • 内存消耗:7.4 MB

性能对比

语言 执行用时 内存消耗 特点
C# 92 ms 25.8 MB 代码结构清晰,性能适中
Python 36 ms 15.1 MB 代码最简洁,性能不错
C++ 4 ms 7.4 MB 性能最优,内存占用最小

代码亮点

  1. 🎯 使用队列实现优雅的迭代器设计
  2. 💡 空间复杂度为O(1),只存储迭代器状态
  3. 🔍 优雅处理空向量的情况
  4. 🎨 代码结构清晰,易于扩展

常见错误分析

  1. 🚫 未正确处理空向量的情况
  2. 🚫 忘记更新迭代器状态
  3. 🚫 队列操作顺序错误
  4. 🚫 未检查索引越界

解法对比

解法 时间复杂度 空间复杂度 优点 缺点
队列法 O(1) O(1) 实现优雅,易扩展 需要额外空间
指针法 O(1) O(1) 空间利用率高 代码较复杂
合并数组法 O(n) O(n) 实现简单 不符合迭代器要求

相关题目

📖 系列导航

🔥 算法专题合集 - 查看完整合集

📢 关注合集更新:点击上方合集链接,关注获取最新题解!目前已更新第281题。

💬 互动交流

感谢大家耐心阅读到这里!希望这篇题解能够帮助你更好地理解和掌握这道算法题。

如果这篇文章对你有帮助,请:

  • 👍 点个赞,让更多人看到这篇文章
  • 📁 收藏文章,方便后续查阅复习
  • 🔔 关注作者,获取更多高质量算法题解
  • 💭 评论区留言,分享你的解题思路或提出疑问

你的支持是我持续分享的动力!

💡 一起进步:算法学习路上不孤单,欢迎一起交流学习!