Arrays 从数组中删除第i个元素,使时间复杂度不依赖于数组大小

Arrays 从数组中删除第i个元素,使时间复杂度不依赖于数组大小,arrays,algorithm,time-complexity,Arrays,Algorithm,Time Complexity,昨天我参加了我的算法分析考试,考试的题目是 描述如何在阵列上执行以下操作,以使所需时间不依赖于阵列大小n. 删除大小为n的数组的第i个元素 删除已排序数组的第i个元素,其中该数组保留在 删除后的排序顺序 对于第一部分,我们可以将第I个值与最后一个值交换,这就是我写的,而对已排序的数组执行此操作将不起作用,因为数组将被取消排序。 现在的问题是,如何为排序数组实现这一点?这样做是否可能没有任何缺点?对于未排序的数组,我们能否以更好的方式执行此操作?我认为此问题的目的是让您了解数组和列表之间的区别

昨天我参加了我的算法分析考试,考试的题目是 描述如何在阵列上执行以下操作,以使所需时间不依赖于阵列大小n.

  • 删除大小为n的数组的第i个元素

  • 删除已排序数组的第i个元素,其中该数组保留在 删除后的排序顺序

对于第一部分,我们可以将第I个值与最后一个值交换,这就是我写的,而对已排序的数组执行此操作将不起作用,因为数组将被取消排序。
现在的问题是,如何为排序数组实现这一点?这样做是否可能没有任何缺点?对于未排序的数组,我们能否以更好的方式执行此操作?

我认为此问题的目的是让您了解数组和列表之间的区别。在前者中,您可以任意访问,但删除和添加将需要移动索引。但是,在列表中,可以在到达节点后以固定时间添加/删除节点。但是,到达需要O(n),因为您没有任意访问权限。如果这是你的提问者的想法,我想他/她希望你创建一个像列表一样的数据结构,但是带有索引,就像Java的ArrayList一样

但是,您也可以使用数组解决这个问题,只需保留一个已删除索引的列表。如果要删除数组[i],只需保留一个新列表“deleteDices”并添加“i”。因此,删除将需要恒定的时间和空间。不需要增加哨兵


编辑:要回答您关于我的评论的问题,不,跳过不会花费O(n)。这是一个简单的列表更新。此外,尽管问题不是这样,但值得知道的是,所有未来的数组遍历都需要遍历新列表,并知道何时跳过。如果列表始终保持排序,则可以有效地执行此操作。我们只需遍历列表一次,就可以确定放置新传入对象的位置。这将需要O(n)。因此,总的来说,删除是在固定的时间内发生的,但是遍历仍然需要O(n)+O(n)=O(n)-第一个大的oh用于原始数组遍历,第二个大的oh用于列表遍历

将第i个元素替换为不能作为数组元素值的特殊符号(例如,0用于正数数组),以将第i个位置标记为空。(此方法有时称为“延迟删除”。

a.用最后一个元素替换第i个元素并减少数组 大小为1

b.用不能作为值的特殊符号替换第i个元素 要标记的数组元素(例如,对于正数数组为0) 第i个位置为空。(这种方法有时被称为“懒惰的”
删除“)

1。“数组”必须是数组(连续块拆分为相同大小的元素)还是提供索引项的集合?2.“删除”时,索引是否移位?数组是提供索引项的集合。索引移位取决于数组大小。我们必须找到一种方法,在不移位索引的情况下删除值。第二个问题要么非常容易引起误解,要么您以误导的方式向我们描述它,因为(假设“数组”和“排序”的通常定义,并且不允许使用辅助数据结构)它没有解决办法。很容易证明可以强制进行n次更新(因此O(n)次):只需删除由n个不同元素组成的数组的第一个元素。我自己认为,对于使用sentinel值的排序数组,没有完美的解决方案,这只是@j_random_hackery的一个变通方法。在某些情况下,删除列表的想法可能会有所帮助,但实际上它会使任意数组元素的访问时间从O(1)恶化到无界时间(甚至不是O(n)):过去可能执行过任意数量的插入和删除,要访问给定的索引i,我们需要检查DeletedDices中无限数量的元素中的每个元素。@j_random_hacker完全同意您的观点,但问题包括一次性删除。因此deletedList方法可以很容易地工作。至于你的问题,我是否可以建议将列表限制为固定大小?达到此大小后,我们实际上会移动数组元素以考虑添加和删除,而不是进一步添加到列表中。然后我们清空列表。因此,在最坏的情况下,访问时间现在是有界的。你还有其他的方法吗?如果我理解正确的话,你把这个问题解释为只有一次删除(在我的某个位置)会发生。虽然这在技术上可能是一个有效的解释,但我认为这不是预期的或最好的解释(例如,因为两个问题都可以用完全相同的方式解决)。但如果这是你的解释,那你为什么要谈论一个叫做“deletedices”的列表呢?它不是只有一个值“deletedIndex”吗?(这可能会假定一些特殊值,例如-1,以表示单个删除尚未发生。)我认为您清空已删除索引列表的想法很好。如果在列表长度达到k时清空列表(并实际移动数组元素),则每次删除都会得到一个具有O(k)访问时间和摊销O(n/k)时间的算法:虽然“清理”需要O(n)时间,但在“清理”之间总会有至少k次删除。如果你选择k=O(sqrt(n)),你可以得到(摊销)O(sqrt(n));如果你选择k=O(n),你可以得到(摊销)固定时间的删除,当然是O(n)访问时间!毫无疑问,“访问时间”是无限的!但问题是设计成“删除不依赖于数组的大小”,我的原始解决方案就是这样做的。克莱