我今天被问到这个问题,我知道答案很简单,但是他让我一直到最后。
编写一个程序,删除存储在包含ArrayList
的{{1}}中的偶数。
这就是我实现它的方式。
1 - 100
ArrayList source = new ArrayList(100);
for (int i = 1; i < 100; i++)
{
source.Add(i);
}
for (int i = 0; i < source.Count; i++)
{
if (Convert.ToInt32(source[i]) % 2 ==0)
{
source.RemoveAt(i);
}
}
//source contains only Odd elements
为我调整它,尽可能多地尝试Yes sirr you are
。我在这部分失败了。
注意:他不想要Linq,没有额外的花里胡哨。只需简单的循环或其他逻辑就可以了
答案 0 :(得分:5)
我敢说复杂性实际上是O(N ^ 2),因为数组中的删除是O(N),并且可能会为每个项目调用它。
所以你有O(N)遍历数组(列表)和O(N)每次删除=&gt; O(N)* O(N)。
由于看起来不太清楚,我将解释推理。在每个步骤中,可以移除物品(假设必须移除每个物品的最坏情况)。在阵列中,移除是通过移位完成的。因此,要删除第一个项目,我需要将所有以下N-1项目向左移动一个位置:
1 2 3 4 5 6...
<---
2 3 4 5 6...
现在,在每次迭代中我需要移位,所以我做N-1 + N-2 + ... + 1 + 0
次移位,得到(N) * (N-1) / 2
(算术系列)的结果,给出O(N ^ 2)的最终复杂度
答案 1 :(得分:4)
让我们这样想:
您正在执行的删除操作的数量是数组长度的一半(如果元素存储在数组中)。所以复杂性至少是O(N)。
你收到的问题让我想你的教授想要你推断存储这些数字的不同方法。
通常,当您具有日志复杂性时,您正在使用不同的结构,如图形或树。
我能想到具有逻辑复杂性的唯一方法是将数字存储在树中(有序树,b树...我们对此进行了详细阐述),但实际上它超出了考试的限制(在数组中输入数字。)
对你有意义吗?
答案 2 :(得分:2)
如果保留两个索引,一个到当前读取位置,另一个到当前写入位置,则性能会明显提高。
int read = 0
int write = 0;
这个想法是read依次查看数组的每个成员; write跟踪列表的当前结束。当我们找到想要删除的成员时,我们会向前移动,但不会写入。
for (int read = 0; read < source.Count; read++) {
if (source[read] % 2 != 0) {
source[write] = source[read];
write += 1;
}
}
然后在最后,告诉ArrayList它的新长度是`write'的当前值。
这会将你从原来的O(n ^ 2)下降到O(n)。
(注意:我没有测试过这个)
答案 3 :(得分:1)
如果你真的必须使用ArrayList并主动删除条目(相反,如果不是首先添加它们)
不按i + 1递增,但i + 2将无需检查是否为奇数。
for (int i = source.Count - 1 ; i > 0; i = i i 2)
{
source.RemoveAt(i);
}
修改:我知道只有当source
按顺序包含1-100中的条目时才会有效。
答案 4 :(得分:1)
在不更改数据结构或对项目在ArrayList中存储的方式做出一些假设的情况下,我无法看到您将如何避免检查每个成员的奇偶校验(因此至少O(n)
复杂度)。也许面试官只是想让你告诉他这是不可能的。
答案 5 :(得分:1)
给定解决方案的问题在于它从头开始,因此每次删除项目时都必须移动整个列表:
Initial List: 1, 2, 3, 4, 5, ..., 98, 99
/ / / /// /
After 1st removal: 1, 3, 4, 5, ..., 98, 99, <empty>
/ /// / /
After 2nd removal: 1, 3, 5, ..., 98, 99, <empty>, <empty>
我使用斜杠试图显示每次删除后列表的移动方式。
您可以通过撤消删除顺序来降低复杂性(并消除我在评论中提到的错误):
for (int i = source.Count-1; i >= 0; --i) {
if (Convert.ToInt32(source[i]) % 2 == 0) {
// No need to re-check the same element during the next iteration.
source.RemoveAt(--i);
}
}
答案 6 :(得分:1)
IF 可以为您提供无限制的并行线程。
假设我们有一个包含n
元素的数组。为每个元素分配一个线程。假设所有线程都完美同步。
O(1)
。)O(log(n))
。)
2**i
块继续此模式(如果您在上半部分添加下半部分的计数)log2(n)
次 - 现在此数组中的每个条目都是下面的赔率计数我愿意打赌,这样的事情就是你朋友心中的答案。