算法初探LeetCode-顶端迭代器

92 阅读2分钟

LeetCode284. 顶端迭代器

请你在设计一个迭代器,在集成现有迭代器拥有的 hasNext 和 next 操作的基础上,还额外支持 peek 操作。

实现 PeekingIterator 类:

  • PeekingIterator(Iterator<int> nums) 使用指定整数迭代器 nums 初始化迭代器。
  • int next() 返回数组中的下一个元素,并将指针移动到下个元素处。
  • bool hasNext() 如果数组中存在下一个元素,返回 true ;否则,返回 false 。
  • int peek() 返回数组中的下一个元素,但  移动指针。

注意: 每种语言可能有不同的构造函数和迭代器 Iterator,但均支持 int next() 和 boolean hasNext() 函数。

示例 1:

输入:
["PeekingIterator", "next", "peek", "next", "next", "hasNext"]
[[[1, 2, 3]], [], [], [], [], []]
输出:
[null, 1, 2, 2, 3, false]

解释:
PeekingIterator peekingIterator = new PeekingIterator([1, 2, 3]); // [1,2,3]
peekingIterator.next();    // 返回 1 ,指针移动到下一个元素 [1,2,3]
peekingIterator.peek();    // 返回 2 ,指针未发生移动 [1,2,3]
peekingIterator.next();    // 返回 2 ,指针移动到下一个元素 [1,2,3]
peekingIterator.next();    // 返回 3 ,指针移动到下一个元素 [1,2,3]
peekingIterator.hasNext(); // 返回 False

提示:

  • 1 <= nums.length <= 1000
  • 1 <= nums[i] <= 1000
  • 对 next 和 peek 的调用均有效
  • nexthasNext 和 peek 最多调用  1000 次

思路分析

考虑将遍历方法放在一个类中实现,将其称作迭代器类,类中持有集合对象,并实现遍历(迭代)方法(hasNext, next等)。这样对客户端不用暴露聚合对象内部(满足迪米特原则),遍历动作本身只在迭代器类中完成(满足单一职责原则),并且实现了遍历方法和聚合对象的分离,当要修改或者添加新的遍历方法时,如previous, hasPrevious等,只需要在迭代器类中修改或添加(满足开闭原则)。​以下展示如何在客户端中通过自定义迭代器遍历自定义聚合类内的元素。客户端声明一个具体聚合类(以抽象聚合接口类型声明),然后初始化该聚合的元素。再通过聚合类的getIterator方法获取具体迭代器类实例(以抽象迭代器类型)。最后调用该Iterator的相关方法完成遍历。

  • 迭代器接口 定义迭代器角色的方法
  • 获取聚合内第一个元素的方法first
  • 获取下一个元素的方法peek (但不推进)
  • 获取下一个元素的方法next (推进) 判断是否有下一个元素的方法hasNext。 具体迭代器类 迭代器接口的实现类。持有聚合元素的集合List,维护当前处理元素的下标index,实现接口方法。

抽象聚合接口 定义聚合角色的方法,增加聚合元素的方法add,移除聚合元素的方法remove,获取一个迭代器示例的方法getIterator(实际上就是JDK集合类例如ArrayList中的iterator方法)。

具体聚合类 抽象聚合接口的实现类,以List持有一个集合实例。实现抽象聚合接口中的add,remove,getIterator方法。

算法代码

class PeekingIterator implements Iterator < Integer > {
    Iterator < Integer > iter;
    Integer next;
    public PeekingIterator(Iterator < Integer > iterator) {
        iter = iterator;
        if (iter.hasNext()) next = iter.next();
    }

    public Integer peek() {
        return next;
    }

    @Override
    public Integer next() {
        Integer ans = next;
        next = iter.hasNext() ? iter.next() : null;
        return ans;
    }

    @Override
    public boolean hasNext() {
        return next != null;
    }
}

结果详情

Snipaste_2023-06-30_15-35-59.png

算法复杂度

  • 空间复杂度:O(1)O(1)
  • 时间复杂度:O(n)O(n)

掘金(JUEJIN)一起进步,一起成长!