【问题标题】:Find the minimum possible difference between two arrays找到两个数组之间的最小可能差异
【发布时间】:2021-03-22 15:07:54
【问题描述】:

我正在努力寻找一种有效的算法来执行以下任务:

给定两个长度相等的数组A和B,两个数组的差定义为:

diff = |a[0]-b[0]| + |a[1]-b[1]| +...+|a[a.length-1]-b[b.length-1]|

我需要找出 A 和 B 之间可能存在的最小差异,并且我最多可以用 A 中的任何其他元素替换 A 中的一个元素。请注意,您不需要执行替换。

例如:

A = [1,3,5]
B = [5,3,1]

如果我们把A[2]换成A[0],那么这两个数组的区别是:

|1-5| + |3-3| + |1-1| = 4

这是两个数组之间可能的最小差异。用 A 中的另一个元素替换 A 中的一个元素不会导致 A 和 B 之间的差异更小。

我将如何解决这个问题?我知道如何解决 O(n^2) 中的问题(蛮力),但很难找到更有效的方法。

谢谢!

【问题讨论】:

  • 排序将使其成为nlogn。会考虑n是否可行。
  • 计算您发布的diff 等式。检查 A 中的哪个元素最接近 diff。相应地改变。没有想过是否有充分的证据,但这应该可以帮助您在n 中解决它。
  • 你不会得到一个只有加/减/比较的 o(n log n)-time 算法,因为元素的独特性会降低。
  • @ShridharRKulkarni 如果我计算差异并检查哪个元素最接近,在这种情况下我会得到 3 或 5。这有什么帮助?
  • @DavidEisenstat 我针对一些测试用例运行了 O(n^2) 解决方案,但它超时了,因此有一种更快的方法。

标签: python algorithm complexity-theory


【解决方案1】:

我将实施 Shridhar 的建议,即在 O(n log n) 时间内分别确定每个元素的最佳修改并采用最佳修改。

import bisect


def abs_diff(x, y):
    return abs(x - y)


def find_nearest(sorted_a, y):
    i = bisect.bisect(sorted_a, y)
    return min(
        sorted_a[max(i - 1, 0) : min(i + 1, len(sorted_a))],
        key=lambda z: abs_diff(z, y),
    )


def improvement(x, y, z):
    return abs_diff(x, y) - abs_diff(z, y)


def min_diff(a, b):
    sorted_a = sorted(a)
    nearest = [find_nearest(sorted_a, y) for y in b]
    return sum(map(abs_diff, a, b)) - max(map(improvement, a, b, nearest))


print(min_diff([1, 3, 5], [5, 3, 1]))

【讨论】:

  • [4, 1, 5, 9][1,3,2,6] 显示的差异为 8,应该是 7。
  • @Soumendra 你怎么看?替换前对应元素的绝对差为3、2、3、3,替换将前3个清零,共8个。
  • 4 -3 = 1, 1 - 1 = 0, 5 - 2 = 3, 9 - 6 = 3; 1 + 0 + 3 + 3 = 7
  • 好的,知道了。你在更换之前做过。我正在寻找替换。
【解决方案2】:

这篇文章错误地回答了这个问题的一个变体,即允许 A 中两个元素的单个 交换。我想我会留下它,因为我正在研究它。

以下是改进的一般可能性。我们可以看到,当我们交换的对具有相反的顺序时(例如,如果 a1 < b1a2 > b2 ,反之亦然),就会发生改进。仔细观察,我们发现下一个质量是最佳候选交换与第一对的重叠最大。

我们可以有一个O(n log n) 例程,首先按它们的低位元素对所有给定的对进行排序,然后按低位元素的降序处理它们。当我们下降时,为a < b 的对保留一个顺序统计树,为b ≤ a 的对保留另一个。按每对的较高元素对树进行排序并保留两个装饰:(1)在左子树中看到的最大间隔,以及(2)在左子树中看到的最低低元素。

对于每个处理过的元素,选择(1)对面树中高元素相等或更低的对和最大间隔(对应第一个树装饰)和(2)具有高于或等于高元素和最低低元素的对面树(对应于第二棵树装饰)。

(由于我们按low 的降序处理这些对,所以看到的lows 将始终等于或高于当前元素。)

(1)

Original:
     a1-----------b1
                     a2----b2
Total: -----------+----

Swapped:
     a1--------------------b2
                  b1-a2
Total: --------------------+-

Result: worse.

(2)

Original:
     a1-----------b1
                     b2----a2
Total: -----------+----

Swapped:
     a1--------------b2
                  b1-------a2
Total: --------------+-------

Result: worse.

(3)

Original:
     a1-----------b1
             a2------b2
Total: -----------+------

Swapped:
     a1--------------b2
             a2---b1
Total: --------------+---

Result: the same.

(4)

Original:
     a1-----------b1
             b2------a2
Total: -----------+------

Swapped:
     a1------b2
                  b1-a2
Total: ------+-

Result: BETTER.
Improvement: 2 * dist(b2, b1)

(5)

Original:
     a1--------------b1
           a2----b2
Total: --------------+----

Swapped:
     a1----------b2
           a2--------b1
Total: ----------+--------

Result: the same.

(6)

Original:
     a1--------------b1
           b2----a2
Total: --------------+----

Swapped:
     a1----b2
                 a2--b1
Total: ----+--

Result: BETTER.
Improvement: 2 * dist(b2, a2)

(7)

Original:
     a1--------------b1
 b2--------a2
Total: --------------+--------

Swapped:
 b2----a1
           a2--------b1
Total: ----+--------

Result: BETTER.
Improvement: 2 * dist(a1, a2)

(8)

Original:
     a1-----------b1
 b2-------------------a2
Total: -----------+-------------------

Swapped:
 b2--a1
                  b1--a2
Total: --+--

Result: BETTER.
Improvement: 2 * dist(a1, b1)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-27
    • 1970-01-01
    • 1970-01-01
    • 2016-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多