Соотношение числа инверсий в скользящей головоломке

#javascript #html #arrays #algorithm #sorting

Вопрос:

Учитывая определение инверсии, как показано ниже

Инверсии: Учитывая доску, инверсией является любая пара плиток i и j, где i

введите описание изображения здесь

У меня есть массив, подобный

arr = [1, 20, 6, 4, 22 , 5 , 12 , 3];

и функция для подсчета количества инверсий:

 function getInvCount(arr){
let inv_count = 0;
for(let i=0; i<arr.length-1; i  ){
    for(let j=i 1; j<arr.length; j  ){
        if(arr[i] > arr[j]) inv_count  ;
    }
}
return inv_count;
 

}

что я хочу сделать, так это, если число инверсий нечетное, внести изменения в массив, чтобы он дал мне четное число инверсий.

Как мне это сделать?

Ответ №1:

На самом деле (спасибо @MattTimmermans за то, что заметил это), здесь должна работать замена любой пары элементов, а не только последовательных.

Давайте возьмем вашу функцию…

 function getInvCount(arr){
  let inv_count = 0;
  for(let i=0; i<arr.length-1; i  ){
    for(let j=i 1; j<arr.length; j  ){
        if(arr[i] > arr[j]) inv_count  ;
    }
  }
}

arr[0] => compared with arr[1], ..., arr[k], arr[k   1], ..., arr[k   x], ..., arr[-1]
arr[1] => compared with arr[2], ..., arr[k], arr[k   1], ..., arr[k   x], ..., arr[-1]
...
arr[k]     => compared with arr[k   1], arr[k   2], ..., arr[k   x], ..., arr[-1]
arr[k   1] => compared with arr[k   2], arr[k   3], ..., arr[k   x], ..., arr[-1]
... 
arr[k   x] => compared with arr[k   x   1], arr[k   x   2], ..., arr[-2], arr[-1]
...
 

… и проанализируйте его, предположив, что мы поменяли местами элементы k и k x индексы. Как это изменило результат?

 arr[0] => compared with arr[1], ..., arr[k   x], arr[k   1], ..., arr[k], ..., arr[-1]
arr[1] => compared with arr[2], ..., arr[k   x], arr[k   1], ..., arr[k], ..., arr[-1]
...
arr[k   x] => compared with arr[k   1], arr[k   2], ..., arr[k], ..., arr[-1]
arr[k   1] => compared with arr[k   2], arr[k   3], ..., arr[k], ..., arr[-1]
...
arr[k] => compared with arr[k   x   1], arr[k   x   2], ..., arr[-2], arr[-1]
...
 

Ну, на самом деле не намного. Любой предшествующий элемент arr[k] по — прежнему сравнивается с обоими arr[k] и arr[k x] -просто в другом порядке (сравнение с arr[k x] идет первым сейчас). И любой элемент, следующий за ними, все равно не сравнивается с этими элементами вообще. Таким образом, все if(arr[i] > arr[j]) проверки из предыдущего «состояния» все еще там, и, по-видимому, их результат тот же.

Единственные измененные сравнения находятся в [k, k x] диапазоне. Для первой строки вот как изменяются проверки:

 a[k] > a[k   1] is replaced by a[k   x] > a[k   1]
a[k] > a[k   2] is replaced by a[k   x] > a[k   2]
...
a[k] > a[k   x] is replaced by a[k   x] > a[k]
 

Кажется, трудно предсказать, как это повлияет на количество, так как нет никакой гарантии, насколько велики эти цифры. Но давайте посмотрим, как влияют проверки для следующей строки:

 a[k   1] > a[k   2] => the same
a[k   1] > a[k   3] => the same
...
a[k   1] > a[k   x] => a[k   1] > a[k]
...
 

Теперь мы видим, что существует всего пара замененных проверок, включающих элемент[k 1] :

 a[k] > a[k   1] => a[k   x] > a[k   1]
a[k   1] > a[k   x] => a[k   1] > a[k]
 

И это ключ: независимо от того, какова a[k 1] ценность, здесь ровно две проверки поменялись местами. То же самое, на самом деле, верно для любого числа от k до k x. Только для a[k x] элемента есть ровно один своп:

 a[k] > a[k   x] => a[k   x] > a[k]
 

Вот почему, независимо от того, какие числа вы поменяете местами, разница будет нечетным числом. Точное число «инверсионного различия» будет эквивалентно (x — 1) * 2 1, поэтому оно строго равно 1 для последовательных чисел, 3 для чисел, разделенных одним элементом и т. Д.

Комментарии:

1. Не имеет значения, какой парой вы поменяетесь.

2. @MattTimmermans Ах, но ты, конечно, прав. ) Обновил ответ.