LeetCode题练习与总结:窥视迭代器--284

233 篇文章 0 订阅
140 篇文章 0 订阅

一、题目描述

请你在设计一个迭代器,在集成现有迭代器拥有的 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 次

二、解题思路

为了实现PeekingIterator类,我们需要在内部维护一个迭代器的状态,并在每次调用nextpeek时更新这个状态。以下是具体的实现步骤:

  1. 在构造函数中,我们需要接收一个整数迭代器nums,并初始化内部状态。我们可以定义一个变量nextElement来存储下一个元素,并在构造函数中立即调用一次next()来填充这个变量。

  2. 实现peek()方法时,我们只需要返回nextElement,而不需要更新迭代器的状态。

  3. 实现next()方法时,我们需要返回nextElement,并在返回之前调用迭代器的next()方法来更新nextElement

  4. 实现hasNext()方法时,我们只需要检查nextElement是否为null,如果是null,则说明没有下一个元素了。

三、具体代码

class PeekingIterator implements Iterator<Integer> {
    private Integer nextElement = null;
    private Iterator<Integer> iterator;

    public PeekingIterator(Iterator<Integer> iterator) {
        // Initialize any member here.
        this.iterator = iterator;
        if (this.iterator.hasNext()) {
            nextElement = this.iterator.next();
        }
    }

    // Returns the next element in the iteration without advancing the iterator.
    public Integer peek() {
        return nextElement;
    }

    // hasNext() and next() should behave the same as in the Iterator interface.
    // Override them if needed.
    @Override
    public Integer next() {
        Integer current = nextElement;
        nextElement = iterator.hasNext() ? iterator.next() : null;
        return current;
    }

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

四、时间复杂度和空间复杂度

1. 时间复杂度
  • PeekingIterator(Iterator<Integer> iterator):构造函数中调用了hasNext()next()方法,这两个操作的时间复杂度都是O(1),因此构造函数的时间复杂度是O(1)。

  • peek():该方法直接返回nextElement变量,不涉及任何循环或递归调用,因此时间复杂度是O(1)。

  • next():该方法首先保存nextElement的值,然后检查迭代器是否有下一个元素,如果有,则调用next()方法。由于每次调用next()时,迭代器都会移动到下一个元素,这个操作的时间复杂度是O(1)。因此,next()方法的时间复杂度也是O(1)。

  • hasNext():该方法检查nextElement是否为null,这是一个直接的变量访问操作,时间复杂度是O(1)。

综上所述,PeekingIterator类中所有方法的时间复杂度都是O(1)。

2. 空间复杂度
  • PeekingIterator(Iterator<Integer> iterator):构造函数中,我们声明了一个nextElement变量和一个iterator变量。这两个变量的大小不依赖于输入数据的大小,因此空间复杂度是O(1)。

  • peek():该方法没有使用额外的空间,所以空间复杂度是O(1)。

  • next():该方法在执行过程中没有使用额外的空间,除了更新nextElement,所以空间复杂度是O(1)。

  • hasNext():该方法没有使用额外的空间,所以空间复杂度是O(1)。

因此,PeekingIterator类的空间复杂度也是O(1),即常数空间复杂度。这意味着无论输入数据的大小如何,PeekingIterator类使用的空间量保持不变。

五、总结知识点

  • 接口实现(Interface Implementation)

    • PeekingIterator类实现了Iterator<Integer>接口,这意味着它必须提供next()hasNext(), 和remove()方法(尽管在这个类中,remove()方法没有被重写)。
  • 成员变量(Member Variables)

    • nextElement:一个Integer类型的成员变量,用于存储下一次调用next()时将返回的元素。
    • iterator:一个Iterator<Integer>类型的成员变量,用于存储传入的迭代器实例。
  • 构造函数(Constructor)

    • 构造函数接收一个Iterator<Integer>类型的参数,并在内部初始化成员变量。
  • 方法重写(Method Overriding)

    • next():重写了Iterator接口中的next()方法。
    • hasNext():重写了Iterator接口中的hasNext()方法。
  • 条件判断(Conditional Statements)

    • 在构造函数和next()方法中使用了if语句来判断迭代器是否有下一个元素。
  • 三目运算符(Ternary Operator)

    • next()方法中使用三目运算符来简洁地决定nextElement的值。
  • 方法调用(Method Calls)

    • 调用传入迭代器的hasNext()next()方法。
  • 封装(Encapsulation)

    • nextElement被封装在类内部,外部无法直接访问,只能通过peek()方法来查看下一个元素。
  • 返回值(Return Values)

    • peek()方法返回nextElement,但不修改它。
    • next()方法返回nextElement,并更新nextElement为迭代器的下一个元素。
    • hasNext()方法返回一个布尔值,表示是否还有更多的元素。
  • 异常处理(Exception Handling)

    • 虽然在这个类中没有显式地处理异常,但实现迭代器时应该考虑可能抛出的NoSuchElementException(当没有更多元素时调用next())。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一直学习永不止步

谢谢您的鼓励,我会再接再厉的!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值