问题的第一部分是:
给定k
排序后的数组,请实现一个迭代器,用于以升序对数组的元素进行迭代。例如:
如果我们有:a1 = {1,3,5}, a2 = {2,4,4,5}
,则调用实现了7次的迭代器的next()
方法将返回:1,2,3,4,4,5,5
。
我成功实现了这一部分,并在下面编写了代码。
第二部分是当next()
方法不返回重复项时实现此迭代器类。对于上面示例中的数组,如果我们调用next()
方法 5 次,我们将得到:1,2,3,4,5
(如果我们调用6次,则需要获取一个异常)。
我认为这并不难-只需使用HashSet
字段,在将它们输入到堆中时将项目添加到此集合中,然后将其实现为一个循环,当您获得唯一的项目时终止。
这种方法的问题在于方法hasNext()
效率不高:您将不得不在以后的调用中迭代将插入到堆中的元素,以了解在将来的{调用中您实际上将具有唯一元素{1}}。
您是否知道如何以有效的方式实现不带重复项的迭代器?
next()
答案 0 :(得分:2)
我认为,对您的原始代码进行少量修改将消除重复项:
创建迭代器时,存储所有数组的max元素(您必须检查每个k
数组的最后一个元素以找到最大值)。
还存储上一次对next()
的调用返回的元素。可以将其初始化为Integer.MIN_VALUE
,并在每次调用next()
时进行修改。
hasNext()
仅检查最后一个元素是否返回
新的next()
重复调用原始的next()
,直到找到比先前返回的元素大的元素为止。
这是修改您的代码的实现(可能需要进行一些小的修改以支持诸如空输入之类的极端情况):
...
private int max; // the maximum element
private int last = Integer.MIN_VALUE; // the last element returned by next()
public ComplexIterator(int[][] lists) {
minHeap = new PriorityQueue<IndexedArrayValue>();
int numOfLists = lists.length;
this.lists = lists;
max = lists[0][lists[0].length-1];
for (int i = 0; i < numOfLists; i++) {
minHeap.add(new IndexedArrayValue(i, 0, lists[i][0]));
if (lists[i][lists[i].length-1] > max) {
max = lists[i][lists[i].length-1];
}
}
}
@Override
public boolean hasNext() {
return last < max;
}
@Override
public Integer next() {
if (!hasNext())
throw new NoSuchElementException();
int value;
do {
IndexedArrayValue indArrVal = minHeap.poll();
int arrayId = indArrVal.arrayId;
int index = indArrVal.index;
value = indArrVal.value;
int nextIndex = index + 1;
if (nextIndex < lists[arrayId].length) {
minHeap.add(new IndexedArrayValue(arrayId, nextIndex, lists[arrayId][nextIndex]));
}
}
while (value <= last);
last = value;
return value;
}
答案 1 :(得分:0)
您可以使用TreeSet使其更简单:
public final class UniqueSortedIterator implements
Iterator<Integer> {
private final Iterator<Integer> base;
public UniqueSortedIterator(int[][] arrays) {
Set<Integer> set = new TreeSet<>();
for (int[] array : arrays) {
for (int item : array) {
set.add(item);
}
}
this.base = set.iterator();
}
@Override
public boolean hasNext() {
return this.base.hasNext();
}
@Override
public Integer next() {
return this.base.next();
}
}
树集既具有独特元素,又保持自然秩序。简单测试:
int[] first = { 1, 3, 5 };
int[] second = { 2, 4, 4, 5 };
Iterator<Integer> usi = new UniqueSortedIterator(new int[][] { first, second });
while (usi.hasNext()) {
System.out.println(usi.next());
}