在迭代python时从剩余数组中找到2个元素的最小差异

Posted

技术标签:

【中文标题】在迭代python时从剩余数组中找到2个元素的最小差异【英文标题】:Find the minimum difference of the 2 elements from the remaining array while iterating python 【发布时间】:2021-11-12 18:14:51 【问题描述】:

我正在遍历数组,每次我想找到与剩余数组差异最小的 2 个元素。 例如,给定 array=[5,3,6,1,3],如果迭代器 i 位于索引 2 处,所以 array[i]=6,我想找到数组中不包括 6 的 2 个元素可以给出的最小差异。

我正在考虑为每次迭代找到第一个和第二个最大元素,但我不知道如何忽略 array[i] 元素。任何提示将不胜感激。

【问题讨论】:

你能有另一个计数器j 如果i==j 然后跳过/忽略那个潜在的价值?如果您可以使用 numpy,请注意 min([1, 2, numpy.nan]) is 1。 numpy 还具有 nanargminnanmin 之类的函数来查找最小值的索引和值,不包括 NaN。 【参考方案1】:

在外部循环中,使用enumerate() 跟踪索引。然后在迭代其余项目(以获得最小差异)的内部循环中,还跟踪索引,以便如果它等于外部循环的索引,我们可以跳过它。

这里有一些解决方案。我们不需要获得所有数字对的所有差异,因为这会导致阶乘时间复杂度(因为我们将获得所有可能的组合/对)。我们可以做的就是简单地对数组进行排序,然后排序一次

    我们只需要得到每个连续数字的差值,例如[1, 3, 10, 11, 12] 我们只需减去 3 - 110 - 311 - 1012 - 11。没有更多的意义,例如12 - 1 因为我们确信它会大于任何连续对。 除了连续对,我们还需要得到交替对,这样如果我们删除一个数字,我们仍然会考虑它的前一个和下一个的差异,例如[10, 12, 14]。如果我们在第 12 项,则不应考虑 12 -1014 - 12。但14 - 10 应该是!

解决方案 1

有点复杂,但时间复杂度只有O(n log n)

对数组进行排序。排序后的值必须包含原始索引。 按排序顺序存储差异,但最多保留 3 项,其中这 3 项差异最小(与有界min heaps 相同的想法)。 为什么是 3 个项目?例如,我们有[1, 10, 12, 14, 100]。然后我们知道最小差为 2,这是12 - 1014 - 12 的结果。对于项目1,最小差异为2,与项目1014100 相同。但是对于12,它不应该是2,因为如果我们删除12,下一个最小差异是14 - 10,即4。这将是最坏的情况。所以我们需要存储最多 3 个最小差异,这里将是来自 12 - 10 的 2 个,来自 14 - 12 的 2 个,来自 14 - 10 的 4 个,这样我们就可以捕捉到 12 的情况,应该选择第三个选项(4 来自14 - 10)。 迭代原始数组。对于每个项目,请查看第一个适用的差异并显示它。这将是不是在减法中使用当前项目导致的差异。
from bisect import insort

numbers = [14, 10, -11, 27, 12, 4, 20]
numbers_sorted = sorted(enumerate(numbers), key=lambda value: value[1])  # O(n log n)

differences = []
for index in range(1, len(numbers_sorted)):  # O(n), the binary search and pop on <differences> are negligible because it is fixed at the constant size of 3
    for prev in range(1, 2 if index == 1 else 3):  # Subtract consecutive and alternating
        diff_tup = (
            numbers_sorted[index][1] - numbers_sorted[index-prev][1],
            numbers_sorted[index-prev],
            numbers_sorted[index],
        )
        insort(differences, diff_tup)
        if len(differences) > 3:
            differences.pop()

for index, num in enumerate(numbers):  # O(n), the iteration of <differences> is negligible because it is fixed at the constant size of 3
    for diff in differences:
        if index != diff[1][0] and index != diff[2][0]:
            print(f"num: min diff diff[0] from diff[1][1] and diff[2][1]")
            break

解决方案 2

更直接,但时间复杂度为O(n ^ 2)

对数组进行排序。排序后的值必须包含原始索引。 在主循环中迭代数组。 对于每个项目,迭代排序的数组。 如果项目是主循环中的项目,则跳过。 否则,减去数字。 如果小于当前最小值,则将其设置为新的最小值。 显示当前数字的最小值
from bisect import insort

numbers = [14, 10, -11, 27, 12, 4, 20]
numbers_sorted = sorted(enumerate(numbers), key=lambda value: value[1])  # O(n log n)

for num_index, num in enumerate(numbers):  # O(n ^ 2)
    min_diff = None
    min_subtractors = None
    
    for index in range(1, len(numbers_sorted)):
        for prev in range(1, 2 if index == 1 else 3):  # Subtract consecutive and alternating
            if num_index == numbers_sorted[index][0] or num_index == numbers_sorted[index-prev][0]:
                continue
            diff = numbers_sorted[index][1] - numbers_sorted[index-prev][1]
            if min_diff is None or diff < min_diff:
                min_diff = diff
                min_subtractors = (numbers_sorted[index-prev][1], numbers_sorted[index][1])

    print(f"num: min diff min_diff from min_subtractors[0] and min_subtractors[1]")

输出

14: min diff 2 from 10 and 12
10: min diff 2 from 12 and 14
-11: min diff 2 from 10 and 12
27: min diff 2 from 10 and 12
12: min diff 4 from 10 and 14
4: min diff 2 from 10 and 12
20: min diff 2 from 10 and 12

【讨论】:

以上是关于在迭代python时从剩余数组中找到2个元素的最小差异的主要内容,如果未能解决你的问题,请参考以下文章

BasicSort 之 SelectSort

选择排序-Java实现

选择排序

第 22 题:如何理解选择排序?

数据结构和算法选择排序

算法一