leetcode
leetcode 201 ~ 250
展开二维向量

展开二维向量

难度:

标签:

题目描述

代码结果

运行时间: 42 ms, 内存: 22.0 MB


/*
题目思路:
通过流 (Stream) 处理二维向量的展开。
使用 flatMap 将二维向量展开为一维流,
然后通过 Iterator 来实现 next() 和 hasNext() 方法。
*/
 
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
public class Vector2D implements Iterator<Integer> {
    private Iterator<Integer> iterator;
 
    public Vector2D(List<List<Integer>> vec) {
        this.iterator = vec.stream()
                            .flatMap(List::stream)
                            .collect(Collectors.toList())
                            .iterator();
    }
 
    @Override
    public Integer next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        return iterator.next();
    }
 
    @Override
    public boolean hasNext() {
        return iterator.hasNext();
    }
}
 

解释

方法:

该题解的思路是在初始化时将二维向量中的所有整数提取出来,存储到一个一维数组 nums 中。同时维护一个位置指针 position,初始值为 -1,表示下一个要返回的元素的位置。当调用 next() 方法时,将 position 加 1,并返回 nums[position] 的值。当调用 hasNext() 方法时,判断 position + 1 是否小于 nums 的长度,如果是则说明还有下一个元素。

时间复杂度:

初始化: O(n), next() 和 hasNext(): O(1)

空间复杂度:

O(n)

代码细节讲解

🦆
在初始化构造函数中,你是如何处理可能存在的空子列表,例如`[[], [1, 2], [], [3]]`?这种情况下的行为和预期输出是什么?
在初始化构造函数中,通过嵌套循环遍历二维向量的每个子列表,并将子列表中的每个元素添加到一维数组`nums`中。对于空的子列表,例如`[]`,由于内部循环依赖于子列表元素的存在,所以空列表将被跳过而不添加任何元素。因此,对于输入`[[], [1, 2], [], [3]]`,一维数组`nums`将只包含`[1, 2, 3]`。预期的行为是顺序返回存在的元素,即先后返回`1`、`2`和`3`,并且对于空的子列表没有任何影响。
🦆
在`next()`方法中,如果在调用时`position`已经是最后一个元素的位置,是否有处理措施防止索引越界?
题解中的`next()`方法在实现时没有显式地处理在`position`已经是最后一个元素位置时的索引越界情况。一般来说,调用`next()`方法前应该使用`hasNext()`方法来检查是否还有元素可返回。如果在`position`为最后一个元素的位置时调用`next()`,将导致索引越界错误。理想的实现应该在`next()`中添加检查,确保`position`不会超出数组长度。
🦆
关于`hasNext()`方法,你提到了它判断`position + 1 是否小于 nums 的长度`,那么在数组为空的情况下,这个方法是否能正确返回`false`?
是的,`hasNext()`方法能够正确处理数组为空的情况。当数组`nums`为空时,它的长度为0。因为`position`初始值为-1,所以`position + 1`等于0。因为0不小于0(数组长度),所以`hasNext()`将返回`false`,正确地指示没有更多的元素可以返回。
🦆
你的解法中完全依赖于`nums`数组来判断和返回元素,如果二维向量在调用过程中被修改,如何保证向量的一致性和类的稳健性?
题解中的方法确实完全依赖于`nums`数组,并没有考虑到原始二维向量在实例化`Vector2D`对象后可能发生的修改。如果二维向量在调用过程中被修改,当前实现并不能反映这些更改,可能导致数据不一致。为了提高稳健性,可以采取以下措施之一:1) 在构造函数中进行深拷贝,确保`nums`数组与原始数据无关联;2) 不存储`nums`数组,而是直接操作原始二维向量,并在每次调用`next()`和`hasNext()`时动态检查和更新当前元素的位置。这些措施可以帮助确保类的行为与外部修改保持一致。

相关问题

二叉搜索树迭代器

实现一个二叉搜索树迭代器类BSTIterator ,表示一个按中序遍历二叉搜索树(BST)的迭代器:
  • BSTIterator(TreeNode root) 初始化 BSTIterator 类的一个对象。BST 的根节点 root 会作为构造函数的一部分给出。指针应初始化为一个不存在于 BST 中的数字,且该数字小于 BST 中的任何元素。
  • boolean hasNext() 如果向指针右侧遍历存在数字,则返回 true ;否则返回 false
  • int next()将指针向右移动,然后返回指针处的数字。

注意,指针初始化为一个不存在于 BST 中的数字,所以对 next() 的首次调用将返回 BST 中的最小元素。

你可以假设 next() 调用总是有效的,也就是说,当调用 next() 时,BST 的中序遍历中至少存在一个下一个数字。

 

示例:

输入
["BSTIterator", "next", "next", "hasNext", "next", "hasNext", "next", "hasNext", "next", "hasNext"]
[[[7, 3, 15, null, null, 9, 20]], [], [], [], [], [], [], [], [], []]
输出
[null, 3, 7, true, 9, true, 15, true, 20, false]

解释
BSTIterator bSTIterator = new BSTIterator([7, 3, 15, null, null, 9, 20]);
bSTIterator.next();    // 返回 3
bSTIterator.next();    // 返回 7
bSTIterator.hasNext(); // 返回 True
bSTIterator.next();    // 返回 9
bSTIterator.hasNext(); // 返回 True
bSTIterator.next();    // 返回 15
bSTIterator.hasNext(); // 返回 True
bSTIterator.next();    // 返回 20
bSTIterator.hasNext(); // 返回 False

 

提示:

  • 树中节点的数目在范围 [1, 105]
  • 0 <= Node.val <= 106
  • 最多调用 105hasNextnext 操作

 

进阶:

  • 你可以设计一个满足下述条件的解决方案吗?next()hasNext() 操作均摊时间复杂度为 O(1) ,并使用 O(h) 内存。其中 h 是树的高度。

锯齿迭代器

锯齿迭代器

窥视迭代器

请你在设计一个迭代器,在集成现有迭代器拥有的 hasNextnext 操作的基础上,还额外支持 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
  • nextpeek 的调用均有效
  • nexthasNextpeek 最多调用  1000

 

进阶:你将如何拓展你的设计?使之变得通用化,从而适应所有的类型,而不只是整数型?

扁平化嵌套列表迭代器

给你一个嵌套的整数列表 nestedList 。每个元素要么是一个整数,要么是一个列表;该列表的元素也可能是整数或者是其他列表。请你实现一个迭代器将其扁平化,使之能够遍历这个列表中的所有整数。

实现扁平迭代器类 NestedIterator

  • NestedIterator(List<NestedInteger> nestedList) 用嵌套列表 nestedList 初始化迭代器。
  • int next() 返回嵌套列表的下一个整数。
  • boolean hasNext() 如果仍然存在待迭代的整数,返回 true ;否则,返回 false

你的代码将会用下述伪代码检测:

initialize iterator with nestedList
res = []
while iterator.hasNext()
    append iterator.next() to the end of res
return res

如果 res 与预期的扁平化列表匹配,那么你的代码将会被判为正确。

 

示例 1:

输入:nestedList = [[1,1],2,[1,1]]
输出:[1,1,2,1,1]
解释:通过重复调用 next 直到 hasNext 返回 false,next 返回的元素的顺序应该是: [1,1,2,1,1]

示例 2:

输入:nestedList = [1,[4,[6]]]
输出:[1,4,6]
解释:通过重复调用 next 直到 hasNext 返回 false,next 返回的元素的顺序应该是: [1,4,6]

 

提示:

  • 1 <= nestedList.length <= 500
  • 嵌套列表中的整数值在范围 [-106, 106]