需要交换的最小数量来改变阵列1阵列2?阵列、最小、数量

2023-09-10 22:35:57 作者:少女心杀手

例如,输入

Array 1 = [2, 3, 4, 5]
Array 2 = [3, 2, 5, 4]

需要交换的最小数量的 2

的互换不需要与相邻小区,任何两个元件可以被交换。

The swaps need not be with adjacent cells, any two elements can be swapped.

推荐答案

由于@IVlad在评论你的问题 Yodaness问题注意要求你算反转数以及掉期不是最小数量。

As @IVlad noted in the comment to your question Yodaness problem asks you to count number of inversions and not minimal number of swaps.

例如:

L1 = [2,3,4,5]
L2 = [2,5,4,3]

交换的最小数量是的一个的(交换5和3 L2 获得 L1 ),但数量是的三的:(5 4),(5 3)和(4 3)对在错误的顺序

The minimal number of swaps is one (swap 5 and 3 in L2 to get L1), but number of inversions is three: (5 4), (5 3), and (4 3) pairs are in the wrong order.

要倒计数的数量最简单的方法如下,从定义:

The simplest way to count number of inversions follows from the definition:

一对元素(P 我,P Ĵ)被称为在置P反转,如果我< j和P 我> P Ĵ。

A pair of elements (pi,pj) is called an inversion in a permutation p if i < j and pi > pj.

在Python的:

def count_inversions_brute_force(permutation):
    """Count number of inversions in the permutation in O(N**2)."""
    return sum(pi > permutation[j]
               for i, pi in enumerate(permutation)
               for j in xrange(i+1, len(permutation)))

您可以指望倒置 O(N *日志(N))使用分而放;征服战略(类似于如何合并排序算法的作品)。下面是从计数反演伪code 转换到Python code:

You could count inversion in O(N*log(N)) using divide & conquer strategy (similar to how a merge sort algorithm works). Here's pseudo-code from Counting Inversions translated to Python code:

def merge_and_count(a, b):
    assert a == sorted(a) and b == sorted(b)
    c = []
    count = 0
    i, j = 0, 0
    while i < len(a) and j < len(b):
        c.append(min(b[j], a[i]))
        if b[j] < a[i]:
            count += len(a) - i # number of elements remaining in `a`
            j+=1
        else:
            i+=1
    # now we reached the end of one the lists
    c += a[i:] + b[j:] # append the remainder of the list to C
    return count, c

def sort_and_count(L):
    if len(L) == 1: return 0, L
    n = len(L) // 2 
    a, b = L[:n], L[n:]
    ra, a = sort_and_count(a)
    rb, b = sort_and_count(b)
    r, L = merge_and_count(a, b)
    return ra+rb+r, L

例如:

>>> sort_and_count([5, 4, 2, 3])
(5, [2, 3, 4, 5])

下面的解决方案在Python从问题:

Here's solution in Python for the example from the problem:

yoda_words   = "in the force strong you are".split()
normal_words = "you are strong in the force".split()
perm = get_permutation(normal_words, yoda_words)
print "number of inversions:", sort_and_count(perm)[0]
print "number of swaps:", number_of_swaps(perm)

输出:

number of inversions: 11
number of swaps: 5

)的定义get_permutation( number_of_swaps()是:

def get_permutation(L1, L2):
    """Find permutation that converts L1 into L2.

    See http://en.wikipedia.org/wiki/Cycle_representation#Notation
    """
    if sorted(L1) != sorted(L2):
        raise ValueError("L2 must be permutation of L1 (%s, %s)" % (L1,L2))

    permutation = map(dict((v, i) for i, v in enumerate(L1)).get, L2)
    assert [L1[p] for p in permutation] == L2
    return permutation

def number_of_swaps(permutation):
    """Find number of swaps required to convert the permutation into
    identity one.

    """
    # decompose the permutation into disjoint cycles
    nswaps = 0
    seen = set()
    for i in xrange(len(permutation)):
        if i not in seen:           
           j = i # begin new cycle that starts with `i`
           while permutation[j] != i: # (i σ(i) σ(σ(i)) ...)
               j = permutation[j]
               seen.add(j)
               nswaps += 1

    return nswaps