arrays - 所有对象都可以按顺序配对吗?

标签 arrays algorithm

首先,这不是作业或类似的东西,这是我上一个问题的暗示性问题Candidate in finding majority element in an array .

n 种对象 O1, O2, ..., On,还有一个数组F[1...n]F[i]是Oi的个数(即有F[i] Ois, array F[1...n] is given), and every F[i] > 0 .

现在使用以下规则配对对象:

如果i != j,Oi可以与Oj配对,
else if i == j, Oi 不能与 Oj 配对。

即,只有两种不同类型的对象可以相互配对。

  1. 输入数组 F[1...n] 是否存在有效的配对方法?给出一个具有最佳时间复杂度的算法来判断真假并证明其正确性。

  2. 如果存在,输出一个有效的配对序列。给出你的算法和时间/空间复杂度分析。

例如, 输入 F[] = {10, 2, 4, 4};

那么至少存在一种有效的配对方式:

2 个 O1 和 2 个 O2 配对,4 个 O1 和 4 个 O3 s 配对,4 个 O1 和 4 个 O4 配对。

一个有效的配对顺序是:

(1,2) (1,2) (1,3) (1,3) (1,3) (1,3) (1,4) (1,4) (1,4) (1 ,4)

最佳答案

检查 O(n) 中是否存在解决方案

sF 的总和.

  • 如果s很奇怪没有解决方案(直观)
  • 如果存在i这样 F[i] > s/2没有解决方案(直观)
  • 否则,存在解决方案(构造证明如下)

在 O(n) 中找到解决方案

# Find s
s = 0
for i in 1..n:
    s += F[i]

# Find m such that F[m] is maximal
m = 1
for i in 1..n:
    if F[i] > F[m]:
         m = i

if s % 2 != 0 or F[m] > s/2:
    fail

a = 1
b = 1

# Pair off arbitrary objects (except those of type m) until F[m] = s/2    
while s/2 > F[m]:
    # Find a type with a non-zero frequency
    until F[a] > 0 and a != m:
        a = a + 1
    # Find another type with a non-zero frequency
    until F[b] > 0 and b != m and b != a:
        b = b + 1

    count = min(F[a], F[b], s/2 - F[m])
    pair(a, b, count)

# Pair off objects of type m with objects of different types
while F[m] > 0:
    # Find a type with a non-zero frequency
    until F[a] > 0 and a != m:
        a = a + 1
    pair(a, m, F[a])

end of algorithm

def pair(a, b, count):
    # Pairs off 'count' pairs of types a and b
    F[a] = F[a] - count
    F[b] = F[b] - count
    s = s - (2 * count)
    output "Pairing off $a and $b ($count times)"

两个while循环都是线性的。第一个 while 循环递增 ab每次迭代至少增加一个,因为在匹配 count 之后对 F[a]为零,或 F[b]为零,或 s/2 = F[m]并且循环终止。 ab最多可以增加 n在所有元素都被访问之前的每一次。第二个 while 循环也是线性的,因为它递增 a在每次迭代期间至少增加 1。

关键的不变量是
(1) F[m]F 的最大元素
(2) F[m] <= s/2
我认为两者在检查时都相当明显。

有了内循环,只要s/2 > F[m]必须至少有两个其他对象类型具有非零频率。如果只有一个,说a , 然后
F[a] + F[m] = s
F[a] = s - F[m] > s - s/2 (来自循环条件)
F[a] > s/2
F[a] > F[m]
这是不变量(1)的矛盾。

因为至少有两种类型具有非零频率(除了 m )循环将能够找到类型 ab并配对对象直到 s/2 = F[m] .

第二个循环很简单。由于正好一半的对象属于 m 类型, 每个类型的对象 m可以与不同类型的对象配对。

关于arrays - 所有对象都可以按顺序配对吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16097772/

相关文章:

c++ - 如何在结构体的 `std::list`处进行搜索?

arrays - 检查元胞数组是否是 Matlab 中另一个元胞数组的子集

jquery - 如果为 null,则使用数组中的另一个图像

计算 1000 到 2000 之间的 9 数量的算法

algorithm - 计算星期几的日期

python - 来自模型的嵌套排列

java - 从数组写入文件

java - 将所有最后的元素拆分并存储到一个数组中

c# - C# 中未知长度的数组

javascript - 在使用匈牙利算法解决非对称 AP 之前减少搜索空间