如何在O(N)时间和O(C)空间复杂度下使用Java8流API仅从列表中删除一个max(min)

如何在O(N)时间和O(C)空间复杂度下使用Java8流API仅从列表中删除一个max(min),java,java-8,max,java-stream,Java,Java 8,Max,Java Stream,下面是一段代码,用于从列表中仅删除一个最大值(在本例中为第一个,但这与此无关)。它在时间上是O(n),在空间上是O(n)(输入之外) public List removeoneofmax(List nums){ int max=整数的最小值; int maxIndex=-1; 迭代器it=nums.Iterator(); for(int i=0;it.hasNext();i++){ 整数temp=it.next(); 如果(最大值nums.get(i)>=nums.get(j)?i:j。这个+答

下面是一段代码,用于从列表中仅删除一个最大值(在本例中为第一个,但这与此无关)。它在时间上是
O(n)
,在空间上是
O(n)
(输入之外)

public List removeoneofmax(List nums){
int max=整数的最小值;
int maxIndex=-1;
迭代器it=nums.Iterator();
for(int i=0;it.hasNext();i++){
整数temp=it.next();
如果(最大值<温度){
maxIndex=i;
最大值=温度;
}
}
nums.remove(maxIndex);
返回nums;
}
1.使用Java8流API的方法的等效性是什么?我想保留时间和空间的复杂性,因此不允许排序

2.实际上,如果将
LinkedList
传递到上述代码中,那么空间复杂度将是
O(C)
(同样,超出了输入),但据我所知,
.stream()
创建了一个额外的数据结构,因此流API在空间中必须至少是
O(N)
。如果我错了,请纠正我。

流解决方案可能如下所示:

int maxIndex = IntStream.range(1, nums.size()).reduce(0, (i, j) -> {
    int left = nums.get(i);
    int right = nums.get(j);
    return Integer.max(left, right) == left ? i : j;
});

nums.remove(maxIndex);
下面将有一个
拆分器


流操作本身不会创建额外的数据结构。

为什么您认为这是空间中的“
O(n)
”?由于已经存在的
列表
不计算在内,因此没有随列表大小扩展的内存需求。这是空间中的
O(1)
,无论您是使用
ArrayList
还是
LinkedList
。使用
CopyOnWriteArrayList
时会有所不同,但这不是算法的责任。
ArrayList.remove(int)
。也许你把它和添加混淆了。然而,即使它是如此昂贵,它也不是您的算法的属性。事实上。除非调用
trimToSize()
,否则它永远不会收缩其数组。但是,对于这种行为没有明确的规范。规范所说的是,容量将根据需要增长(非线性,以保证“固定摊销时间成本”)。@GA1 Holger的最后一点不仅适用于ArrayList,也适用于几乎所有其他类型。HashMap内部数组在删除元素时也不会收缩。@Holger您在这里的评论回答了OP提出的更多问题,然后是我发布的实际答案。请您添加这些作为答案,我将非常乐意投票。通常,建议使用现有的方法,但在这里,这只会使代码更加复杂。整个lambda表达式可以简化为
(i,j)->nums.get(i)>=nums.get(j)?i:j
。这个+答案正是我想要的
int maxIndex = IntStream.range(1, nums.size()).reduce(0, (i, j) -> {
    int left = nums.get(i);
    int right = nums.get(j);
    return Integer.max(left, right) == left ? i : j;
});

nums.remove(maxIndex);