Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Big o 最小互换数量?_Big O - Fatal编程技术网

Big o 最小互换数量?

Big o 最小互换数量?,big-o,Big O,数组中类型a和B的字符串中有N个字符(每种类型的数量相同)。如果我们只能交换两个相邻字符,那么确保没有两个相邻字符相同的最小交换次数是多少? 例如,输入为: AAAABBBB 交换的最小数目是6,以使数组成为ABABABAB。但是,对于任何类型的输入,您将如何解决它?我只能想到O(N^2)解。也许是某种类型的?如果我们只需要计算掉期,那么我们可以使用O(N) 为了简单起见,让我们假设N个元素的数组X应该变成ABAB GetCount() swaps = 0, i = -1, j = -

数组中类型a和B的字符串中有N个字符(每种类型的数量相同)。如果我们只能交换两个相邻字符,那么确保没有两个相邻字符相同的最小交换次数是多少? 例如,输入为:

AAAABBBB

交换的最小数目是6,以使数组成为ABABABAB。但是,对于任何类型的输入,您将如何解决它?我只能想到O(N^2)解。也许是某种类型的?

如果我们只需要计算掉期,那么我们可以使用O(N)

为了简单起见,让我们假设N个元素的数组X应该变成ABAB

GetCount()
    swaps = 0, i = -1, j = -1
    for(k = 0; k < N; k++)
        if(k % 2 == 0)
            i = FindIndexOf(A, max(k, i))
            X[k] <-> X[i]
            swaps += i - k
        else
            j = FindIndexOf(B, max(k, j))
            X[k] <-> X[j]
            swaps += j - k
    return swaps

FindIndexOf(element, index)
    while(index < N)
        if(X[index] == element) return index
        index++
    return -1; // should never happen if count of As == count of Bs
GetCount()
互换=0,i=-1,j=-1
对于(k=0;k
基本上,我们从左到右运行,如果发现一个放错位置的元素,它将与
O(1)
中的正确元素(例如
abbbba**-->abAbbbB**
)交换。同时,交换被视为相邻元素的序列将被交换。变量
i
j
分别用于缓存下一个
A
B
的索引,以确保所有FindIndexOf调用都在
O(N)
中完成

如果我们需要按掉期进行排序,那么我们不能做得比O(N^2)更好


大致思路如下。让我们考虑一下你的例子:<代码> AAAABBB< < /代码>。
B
s中的一个需要O(N)交换才能到达AB。。。位置,另一个
B
需要O(N)才能到达A B AB。。。位置等。因此我们在末尾得到O(N^2)。

观察到,如果任何解决方案将交换同一字母的两个实例,那么我们可以通过删除该交换来找到更好的解决方案,这必然没有效果。因此,最佳解决方案只交换不同的字母

让我们将字母字符串视为字符串中一种字母(任意选择,例如
A
)的索引数组。因此,
aaaabbb
将表示为
[0,1,2,3]
,而
ABABABAB
将表示为
[0,2,4,6]

我们知道同一个字母的两个实例永远不会在最佳解决方案中互换。这让我们始终可以安全地用索引数组的第一个元素识别
A
的第一个(最左边)实例,用第二个元素识别第二个实例,等等。它还告诉我们,在最优解的每个步骤中,数组总是按排序顺序排列的

由于最优解决方案的每一步都交换不同的字母,我们知道索引数组在每一步都只通过一次递增或递减一个元素来演化

长度
n=2k
的初始字符串将具有长度
k
的数组表示形式
A
。最佳解决方案将此阵列转换为

ODDS = [1, 3, 5, ... 2k]

因为我们知道在最优解中,一个字母的实例不会相互传递,所以我们可以得出结论,最优解必须花费
min(abs(赔率[0]-a[0])、abs(EVENS[0]-a[0]))
交换,才能将第一个实例置于正确的位置

通过实现
EVENS
赔率
选择只进行一次(而不是每个字母实例进行一次),并在整个数组中求和,我们可以将所需交换的最小数量计算为

define count_swaps(length, initial, goal)
  total = 0
  for i from 0 to length - 1
    total += abs(goal[i] - initial[i])
  end
  return total
end

define count_minimum_needed_swaps(k, A)
  return min(count_swaps(k, A, EVENS), count_swaps(k, A, ODDS))
end
注意,
count\u minimum\u needed\u swap
所暗示的循环迭代次数是
2*k=n
;它在
O(n)
时间内运行


通过注意到
count\u minimum\u needed\u swaps
中哪个项较小,我们还可以判断这两个目标状态中哪一个是最优的

因为您知道N,所以可以简单地编写一个循环,生成值而不需要交换

#define N 4
char array[N + N];

for (size_t z = 0; z < N + N; z++)
{
    array[z] = 'B' - ((z & 1) == 0);
}

return 0;   // The number of swaps
#定义N 4
字符数组[N+N];
对于(大小_t z=0;z
@Nemo和@AlexD是对的。该算法为n^2阶@尼莫误解了我们正在寻找一个两个相邻字符不相同的重新排序,所以我们不能使用,如果a是在B之后,它们是无序的

让我们看看最小交换次数

我们不在乎我们的第一个字符是A还是B,因为我们可以应用相同的算法,但使用A代替B,反之亦然。因此,让我们假设单词
word\N
的长度为2N,其中N为As,N为Bs,从A开始(我使用长度2N来简化计算)

我们要做的是尝试将下一个B向右移动到这个A,而不考虑其他字符的位置,因为这样我们就可以减少重新排列新词的问题
word_{N-1}
。如果单词有2个以上的字符,我们还假设下一个B不仅仅在A之后,因为第一步已经完成,我们将问题归结为下一组字符,
word{N-1}

下一个B应该尽可能在最坏的情况下,所以它在单词的一半之后,所以我们需要$N-1$掉期将这个B放在A之后(可能小于这个)。然后我们的单词可以简化为
单词N=[abword{N-1}]

我们认为我们必须像大多数N-1次那样执行此算法,因为最后一个单词(
word_1
)将已经排序。我们必须执行算法N-1次

N_互换=(N-1)*N/2

其中N是首字母长度的一半

让我们看看为什么我们可以对
WORD_{N-1}
应用相同的算法,同时假设第一个单词是A。在这种情况下,它比fi更重要
#define N 4
char array[N + N];

for (size_t z = 0; z < N + N; z++)
{
    array[z] = 'B' - ((z & 1) == 0);
}

return 0;   // The number of swaps
Prelude Data.List> let is = elemIndices 'B' "AAAABBBB" 
                   in minimum 
                   $ map (sum . zipWith ((abs .) . (-)) is) [[1,3..],[0,2..]]
6 --output