Яка ймовірність того, що масив залишиться незмінним?


74

Це питання було задане в інтерв'ю Microsoft. Дуже цікаво дізнатися, чому ці люди задають такі дивні запитання щодо ймовірності?

Дано rand (N), генератор випадкових випадків, який генерує випадкове число від 0 до N-1.

int A[N]; // An array of size N
for(i = 0; i < N; i++)
{
    int m = rand(N);
    int n = rand(N);
    swap(A[m],A[n]);
}

EDIT: Зверніть увагу, що насіння не зафіксовано.

яка ймовірність того, що масив A залишається незмінним?
Припустимо, що масив містить унікальні елементи.


9
Для фіксованого Nта фіксованого насіння ймовірність є 0або 1тому, що це зовсім не випадково.
Містичний

25
Якщо це дійсно програма C (як пропонують теги), ймовірність дорівнює 1. Елементи масиву передаються за значенням (у C немає передачі за посиланням), тому swapфункція не може змінити вміст A. \ редагувати: Ну, це swapможе бути і макрос ... сподіваємось, що це не так :)
Рейма

13
@reima: це може бути макрос.
Євген Клюєв

4
Подумайте про запитання на math.stackexchange.com. Перефразування: з урахуванням випадкових a_i, b_i, яка ймовірність того, що перестановка (a_1 b_1) (a_2 b_2) ... (a_n b_n) = тотожність у симетричній групі S_n?
sdcvvc

11
Е-е ... ніхто не розумів, що А НІКОЛИ НЕ ІНІЦІАЛІЗОВАНО?
Кен Беккет

Відповіді:


29

Ну, я трохи розважився цим. Перше, про що я згадав, коли вперше прочитав проблему, це теорія груп (зокрема, симетрична група S n ). Цикл for просто будує перестановку σ в S n , складаючи транспозиції (тобто свопи) на кожній ітерації. Моя математика не така вражаюча, і я трохи іржавий, тож якщо мої позначення не відповідають.


Огляд

Нехай Aбуде подією того, що наш масив не змінився після перестановки. Ми в кінцевому рахунку , прошу знайти ймовірність події A, Pr(A).

Моє рішення намагається виконати наступну процедуру:

  1. Розглянемо всі можливі перестановки (тобто переупорядкування нашого масиву)
  2. Розбийте ці перестановки на непересечені набори на основі кількості так званих транспозицій ідентичності, які вони містять. Це допомагає зменшити проблему до рівномірного перестановок.
  3. Визначте ймовірність отримання перестановки тотожності, враховуючи, що перестановка є парною (і має певну довжину).
  4. Підсумуйте ці ймовірності, щоб отримати загальну ймовірність масиву незмінною.

1) Можливі результати

Зверніть увагу, що кожна ітерація циклу for створює обмін (або транспозицію ), що призводить до однієї з двох речей (але ніколи не обох):

  1. Два елементи поміняні місцями.
  2. Елемент міняється місцями між собою. Для наших цілей масив незмінний.

Ми позначаємо другий випадок. Давайте визначимо транспонування ідентичності наступним чином:

Транспозиції ідентичності виникає , коли число обміняно з самими собою. Тобто, коли n == m у наведеному вище циклі for.

Для будь-якого даного циклу перерахованого коду ми складаємо Nтранспозиції. У 0, 1, 2, ... , Nцьому "ланцюжку" можуть бути перенесення ідентичності.


Наприклад, розглянемо N = 3випадок:

Given our input [0, 1, 2].
Swap (0 1) and get [1, 0, 2].
Swap (1 1) and get [1, 0, 2]. ** Here is an identity **
Swap (2 2) and get [1, 0, 2]. ** And another **

Зверніть увагу, що існує непарна кількість неідентичних транспозицій (1), і масив змінено.


2) Розділення на основі кількості транспозицій ідентифікаційних даних

Нехай K_iбуде подією, коли iтранспозиції ідентичності з’являються у певній перестановці. Зверніть увагу, що це утворює вичерпний розділ усіх можливих результатів:

  • Жодна перестановка не може мати дві різні величини транспозицій тотожності одночасно, і
  • Всі можливі перестановки повинні мати між 0і Nпосвідченням транспозиції.

Таким чином, ми можемо застосувати закон повної ймовірності :

                      

Тепер ми нарешті можемо скористатися розділом. Зверніть увагу, що коли кількість неідентичних транспозицій непарна, масив не може залишитися незмінним *. Отже:

                        

* З теорії груп перестановка є парною або непарною, але ніколи не обома. Тому непарна перестановка не може бути перестановкою тотожності (оскільки перестановка тотожності є парною).

3) Визначення ймовірностей

Отже, ми повинні визначити дві ймовірності для N-iпарних:

  1. Pr (K_i)
  2. Pr (A | K_i)

Перший термін

Перший член, Pr (K_i)представляє ймовірність отримання перестановки з iтранспозиціями ідентичності. Це виявляється двочленним, оскільки для кожної ітерації циклу for:

  • Результат не залежить від результатів до нього, і
  • Імовірність створення транспозиції ідентичності однакова, а саме 1/N.

Таким чином, для Nвипробувань ймовірність отримання iтранспозицій ідентичності становить:

                      

Другий термін

Так що, якщо ви зробили це настільки далеко, ми звели задачу до знаходження Pr (A | K_i)для N - iпарне. Це представляє ймовірність отримання заданої перестановки ідентичностіi того, що транспозиції є тотожностями. Я використовую наївний підхід підрахунку, щоб визначити кількість способів досягнення перестановки тотожності над кількістю можливих перестановок.

Спочатку розглянемо перестановки (n, m)та (m, n)еквівалент. Тоді нехай Mбуде можливою кількість неідентичних перестановок. Ми будемо використовувати цю кількість часто.

                              

Мета тут - визначити кількість способів поєднання колекцій транспозицій для формування перестановки ідентичності. Я спробую побудувати загальне рішення поряд із прикладом N = 4.


Давайте розглянемо N = 4випадок з усіма транспозиціями ідентичності ( тобто i = N = 4 ). Нехай Xпредставляють транспонування ідентичності. Для кожного з них Xє свої Nможливості (вони:) n = m = 0, 1, 2, ... , N - 1. Таким чином, є N^i = 4^4можливості для перестановки ідентичності. Для повноти ми додамо біноміальний коефіцієнт, C(N, i)щоб розглянути порядок транспозицій тотожності (тут він просто дорівнює 1). Я намагався зобразити це нижче з фізичним розташуванням елементів зверху та кількістю можливостей нижче:

I  =  _X_   _X_   _X_   _X_
       N  *  N  *  N  *  N  * C(4, 4) => N^N * C(N, N) possibilities

Тепер явно не підмінюючи N = 4і i = 4, ми можемо розглянути загальний випадок. Поєднуючи вищезазначене із знайденим раніше знаменником, знаходимо:

                          

Це інтуїтивно зрозуміло. Насправді, будь-яке інше значення, крім того, що, 1напевно, мало б вас насторожити. Подумайте: нам дана ситуація, в якій, Nяк кажуть, усі транспозиції є ідентичністю. Що, мабуть, не змінило масив у цій ситуації? Очевидно, що 1.


Тепер, знову ж таки N = 4, давайте розглянемо 2 транспозиції ідентичності ( тобто i = N - 2 = 2 ). Як домовленість, ми розмістимо дві ідентичності в кінці (і будемо замовляти їх пізніше). Зараз ми знаємо, що нам потрібно вибрати дві транспозиції, які при складанні стануть перестановкою ідентичності. Давайте розмістимо будь-який елемент у першому місці, назвемо його t1. Як зазначено вище, існують Mможливості, якщо припустити, що t1це не ідентичність (це не може бути, оскільки ми вже розмістили дві).

I  =  _t1_   ___   _X_   _X_
       M   *  ?  *  N  *  N

Єдиним елементом, який міг би потрапити у друге місце, є зворотне значення t1, яке є насправді t1(і це єдине за унікальністю зворотного). Ми знову включаємо біноміальний коефіцієнт: у цьому випадку ми маємо 4 відкритих розташування, і ми хочемо розмістити 2 ідентифікаційні перестановки. Скільки способів ми можемо це зробити? 4 оберіть 2.

I  =  _t1_   _t1_   _X_   _X_ 
       M   *  1   *  N  *  N  * C(4, 2) => C(N, N-2) * M * N^(N-2) possibilities

Знову дивлячись на загальний випадок, це все відповідає:

                      

Нарешті, ми робимо N = 4справу без жодної транспозиції ідентичності ( тобто i = N - 4 = 0 ). Оскільки можливостей дуже багато, це починає бути складним, і ми повинні бути обережними, щоб не подвоїти рахунок. Починаємо так само, розміщуючи один елемент у першому місці та розробляючи можливі комбінації. Спочатку візьміть найпростіший: те саме транспонування 4 рази.

I  =  _t1_   _t1_   _t1_   _t1_ 
       M   *  1   *  1   *  1   => M possibilities

Давайте тепер розглянемо два унікальних елементи t1і t2. Є Mможливості для t1і тільки M-1можливості для t2(оскільки t2не може бути рівним t1). Якщо ми вичерпаємо всі домовленості, ми залишимо такі схеми:

I  =  _t1_   _t1_   _t2_   _t2_ 
       M   *  1   *  M-1 *  1   => M * (M - 1) possibilities   (1)st

   =  _t1_   _t2_   _t1_   _t2_
       M   *  M-1 *  1   *  1   => M * (M - 1) possibilities   (2)nd

   =  _t1_   _t2_   _t2_   _t1_
       M   *  M-1 *  1   *  1   => M * (M - 1) possibilities   (3)rd

Тепер давайте розглянемо три унікальних елементів, t1, t2, t3. Давайте розмістимо t1спочатку, а потім t2. Як завжди, ми маємо:

I  =  _t1_   _t2_   ___   ___ 
       M   *  ?   *  ?  *  ?  

Ми поки не можемо сказати, скільки можливо t2 може бути ще, і ми побачимо, чому через хвилину.

Зараз ми займаємо t1третє місце. Зверніть увагу, t1треба їхати туди, оскільки якби ми йшли в останньому місці, ми б просто відтворили (3)rdугоду вище. Подвійний підрахунок - це погано! Це залишає третій унікальний елемент t3у кінцевій позиції.

I  =  _t1_   _t2_   _t1_   _t3_ 
       M   *  ?   *  1  *   ?  

То чому нам довелося взяти хвилину, щоб t2уважніше розглянути кількість s? Транспозиції t1та t2 не можуть бути несуміжними перестановками ( тобто вони повинні спільно використовувати одну (і лише одну, оскільки вони також не можуть бути рівними) своїх nабо m). Причиною цього є те, що якби вони були несумісними, ми могли б поміняти місцями перестановки. Це означає, що ми будемо двічі підраховувати (1)stдомовленості.

Say t1 = (n, m). t2повинен мати форму (n, x)або (y, m)для деяких xі yдля того, щоб бути несуміжними. Зверніть увагу , що xне може бути nабо mй yбагато з них НЕ буде nабо m. Таким чином, кількість можливих перестановок, які t2можуть бути, є насправді2 * (N - 2) .

Отже, повертаючись до нашого макету:

I  =  _t1_    _t2_    _t1_   _t3_ 
       M   * 2(N-2) *  1   *  ?  

Тепер t3має бути зворотне до складу t1 t2 t1. Давайте зробимо це вручну:

(n, m)(n, x)(n, m) = (m, x) 

Так t3повинно бути (m, x). Зверніть увагу, що це не є несумісним t1і не дорівнює жодному, t1або t2тому для цього випадку немає подвійного підрахунку.

I  =  _t1_    _t2_    _t1_   _t3_ 
       M   * 2(N-2) *  1  *   1    => M * 2(N - 2) possibilities   

Нарешті, поклавши все це разом:

        

4) Склавши все це разом

От і все. Працюйте назад, підставивши те, що ми знайшли, у вихідне підсумовування, подане на кроці 2. Я обчислив відповідь наN = 4 випадок нижче. Він дуже точно відповідає емпіричному числу, знайденому в іншій відповіді!

         N = 4
         М = 6 _________ _____________ _________
                  | Pr (K_i) | Pr (A | K_i) | Товар |
         _________ | _________ | _____________ | _________ |
        | | | | |
        | i = 0 | 0,316 | 120/1296 | 0,029 |
        | _________ | _________ | _____________ | _________ |
        | | | | |
        | i = 2 | 0,211 | 6/36 | 0,035 |
        | _________ | _________ | _____________ | _________ |
        | | | | |
        | i = 4 | 0,004 | 1/1 | 0,004 |
        | _________ | _________ | _____________ | _________ |
                            | | |
                            | Сума: | 0,068 |
                            | _____________ | _________ |

Правильність

Було б круто, якби тут був застосований результат теорії груп - і, можливо, він є! Це, безумовно, допомогло б повністю зникнути весь цей нудний підрахунок (і скоротити проблему до чогось набагато елегантнішого). Я перестав працювати в N = 4. Бо N > 5те, що наведено, лише наближує (наскільки добре, я не впевнений). Цілком зрозуміло, чому саме це, якщо задуматися: наприклад, з огляду на N = 8транспозиції, існують чітко способи створення ідентичності з чотирма унікальними елементами, які не враховані вище. Кількість способів стає, здається, складнішим для підрахунку, оскільки перестановка стає довшою (наскільки я можу зрозуміти ...).

У будь-якому випадку, я точно не міг зробити щось подібне в рамках інтерв’ю. Якби мені пощастило, я дійшов би до кроку знаменника. Крім цього, це здається досить неприємним.


Я не думаю, що ви праві, оскільки між подіями є залежності - Pr (A і K = 0) + Pr (A і K = 1) + ... + Pr (A і K = N). І згідно з вашим аналізом ви припускаєте, що ні.
barak1412

Хм, дякую за примітку. Можливо, я застосовую його неправильно, але я розглядав результат: Нехай K_1, K_2, ..., K_N буде розділом нашого простору S. Нехай A є підпростором S. Тоді (я, здається, іноді називається загальною ймовірністю): P (A) = Сума Pr (A | K_i) * P (K_i). Я майже впевнений, що поділ таким чином також створює розділ: жодна перестановка не може бути в двох різних підмножинах (оскільки вона має одну кількість ідентичностей), і всі можливі перестановки враховані.
Користувач

afaict те, що у вас добре, (за винятком числівника, що з'являється з нізвідки ...)
andrew cooke

Звичайно, відповідь є слабкою у цьому відношенні. Я намагався дати зрозуміти приклад, але, правда, це не дуже добре. Здебільшого це просто спроби підрахувати та рахувати ефективно, де це можливо (за допомогою шаблонів того, що могло б статися). Я перевірив це для кількох випадків, але, очевидно, не для всіх; там, мабуть, повинна бути зірочка. Якби був хороший спосіб обчислення такої ймовірності, я думаю, це рішення було б досить акуратним. Мені це, безумовно, уникло! :)
Користувач

1
Це правильна відповідь. Він потрапляє до всіх потрібних слів ("перестановка", "транспонування", "ідентичність"), і міркування правильне: 1) враховуйте кількість фактичних транспозицій, 2) вважайте, що вам потрібна парна кількість транспозицій і 3) підраховуйте всі кількість переставлених пар, що складають перестановку ідентичності. Однак одна критика: якби ви писали речі більш стисло, то, мабуть, було б більш очевидно, що ви все зрозуміли.
Джеремі

20

Дуже цікаво дізнатися, чому ці люди задають такі дивні запитання щодо ймовірності?

Такі запитання задаються, оскільки вони дозволяють інтерв’юеру отримати уявлення про інтерв’юйованого

  • можливість читання коду (дуже простий код, але хоча б щось)
  • можливість аналізу алгоритму для ідентифікації шляху виконання
  • навички застосування логіки для пошуку можливих результатів та крайнього випадку
  • міркування та навички вирішення проблем, коли вони працюють над проблемою
  • навички спілкування та роботи - чи ставлять вони запитання, чи працюють ізольовано на основі наявної інформації

... і так далі. Ключ до запитання, яке розкриває ці атрибути співрозмовника, - це наявність коду, який є оманливо простим. Це витрушує самозванців, які не кодують; зарозумілий стрибок до неправильного висновку; ледачий або незначний комп’ютерник знаходить просте рішення і перестає шукати. Часто, як кажуть, справа не в тому, чи отримуєте ви правильну відповідь, а в тому, чи вражаєте ви своїм процесом мислення.


Я також спробую відповісти на запитання. В інтерв'ю я б пояснив себе, а не дав однорядкову письмову відповідь - це тому, що навіть якщо моя "відповідь" неправильна, я можу продемонструвати логічне мислення.

A залишиться незмінним - тобто елементи в тих самих положеннях - коли

  • m == nу кожній ітерації (так, щоб кожен елемент міняв місцями лише сам); або
  • будь-який елемент, який замінюється, повертається у початкове положення

Перший випадок - це "простий" випадок, який дає duedl0r, випадок, коли масив не змінено. Це може бути відповіддю, тому що

яка ймовірність того, що масив A залишається незмінним?

якщо масив змінюється в, i = 1а потім повертається назад в i = 2, він перебуває у вихідному стані, але він не `` залишився колишнім '' - його змінили, а потім змінили назад. Це може бути розумною технікою.

Потім, розглядаючи ймовірність того, що елементи будуть замінені та замінені назад, - я думаю, що під час інтерв’ю цей розрахунок знаходиться вище моєї голови. Очевидним міркуванням є те, що це не повинно бути зміною - змінити зворотний своп, міг би бути такий же легкий своп між трьома елементами, міняючи місцями 1 і 2, потім 2 і 3, 1 і 3 і, нарешті, 2 і 3. І продовжуючи, можуть бути обміни між 4, 5 або більше елементами, які є такими "круговими".

Насправді, а не розглядати випадки , коли масив є незмінним, він може бути простіше розглянути випадки , коли вона буде змінена. Поміркуйте, чи можна цю проблему відобразити на такій відомій структурі, як трикутник Паскаля .


Це важка проблема. Я погоджуюсь, що це занадто важко вирішити на співбесіді, але це не означає, що занадто важко запитувати на співбесіді. Бідний кандидат не матиме відповіді, середній кандидат вгадає очевидну відповідь, а хороший кандидат пояснить, чому на проблему занадто важко відповісти.

Я вважаю це "відкритим" питанням, яке дає інтерв'юеру уявлення про кандидата. З цієї причини, хоча це занадто важко вирішити під час співбесіди, це гарне запитання під час співбесіди. Задавати питання - це більше, ніж просто перевірка правильної чи неправильної відповіді.


як щодо довших циклів? вони можуть не існувати? або вони все більш малоймовірні в міру збільшення тривалості циклу? можна було б сподіватися, що один із двох випадків відповідає дійсності, і було б добре дати якусь кількісну оцінку того, наскільки вони важливі.
andrew cooke

2
на жаль, це не йде так ... коли ви поміняєте місцями 1 і 2, потім 2 і 3, а потім 1 і 3, це буде не перший стан ... останній потрібно поміняти знову ...
Ердем E.

3
правильно, але це не є доказом того, що жодна послідовність із більш ніж 2 обмінами неможлива. у Вашому аргументі, наприклад, чотири обміни все робить нормально.
andrew cooke

Більш тривалі цикли @andrewcooke можуть існувати, але припускають, що вони, ймовірно, зменшуються експоненціально по відношенню до їх довжини. Імовірно, буде задіяна якась межа.
Кірк Бродхерст,

ой, вибач переможцю, думав ти говориш зі мною!
andrew cooke

10

Нижче наведено код С для підрахунку кількості значень 2N-набору індексів, які може отримати ренд, та обчислення ймовірності. Починаючи з N = 0, він показує відліки 1, 1, 8, 135, 4480, 189125 та 12450816, з імовірностями 1, 1, .5, .185185, .0683594, .0193664 та .00571983. Підрахунок не відображається в Енциклопедії цілочисельних послідовностей , тому або у моїй програмі є помилка, або це дуже незрозуміла проблема. Якщо так, проблему не призначено вирішити претендентом на роботу, а викрити деякі їхні процеси мислення та способи боротьби з розчаруванням. Я б не вважав це хорошою проблемою співбесіди.

#include <inttypes.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>


#define swap(a, b)  do { int t = (a); (a) = (b); (b) = t; } while (0)


static uint64_t count(int n)
{
    // Initialize count of how many times the original order is the result.
    uint64_t c = 0;

    // Allocate space for selectors and initialize them to zero.
    int *r = calloc(2*n, sizeof *r);

    // Allocate space for array to be swapped.
    int *A = malloc(n * sizeof *A);

    if (!A || !r)
    {
        fprintf(stderr, "Out of memory.\n");
        exit(EXIT_FAILURE);
    }

    // Iterate through all values of selectors.
    while (1)
    {
        // Initialize A to show original order.
        for (int i = 0; i < n; ++i)
            A[i] = i;

        // Test current selector values by executing the swap sequence.
        for (int i = 0; i < 2*n; i += 2)
        {
            int m = r[i+0];
            int n = r[i+1];
            swap(A[m], A[n]);
        }

        // If array is in original order, increment counter.
        ++c;    // Assume all elements are in place.
        for (int i = 0; i < n; ++i)
            if (A[i] != i)
            {
                // If any element is out of place, cancel assumption and exit.
                --c;
                break;
            }

        // Increment the selectors, odometer style.
        int i;
        for (i = 0; i < 2*n; ++i)
            // Stop when a selector increases without wrapping.
            if (++r[i] < n)
                break;
            else
                // Wrap this selector to zero and continue.
                r[i] = 0;

        // Exit the routine when the last selector wraps.
        if (2*n <= i)
        {
            free(A);
            free(r);
            return c;
        }
    }
}


int main(void)
{
    for (int n = 0; n < 7; ++n)
    {
        uint64_t c = count(n);
        printf("N = %d:  %" PRId64 " times, %g probabilty.\n",
            n, c, c/pow(n, 2*n));
    }

    return 0;
}

1
Незалежна програма Python дає однакові результати до N = 6, тож ваша реалізація правильна. Кожен підрахунок можна поділити на N ^ 3, але це також не відображається в OEIS.
ecatmur

10

Поведінка алгоритму може бути змодельоване як ланцюг Маркова над симетричної групою S N .

Основи

В N елементи масиву Aможуть бути розташовані в N ! різні перестановки. Пронумеруємо ці перестановки від 1 до N !, Наприклад, шляхом лексикографічного упорядкування. Отже, стан масиву Aв будь-який момент в алгоритмі може бути повністю охарактеризований числом перестановки.

Наприклад, для N = 3, одна можлива нумерація всіх 3! = 6 перестановок може бути:

  1. abc
  2. акб
  3. бак
  4. bca
  5. таксі
  6. cba

Імовірності переходу держави

На кожному кроці алгоритму стан Aабо залишається незмінним, або переходить з однієї з цих перестановок в іншу. Зараз нас цікавлять ймовірності цих змін стану. Назвемо Pr ( ij ) ймовірністю зміни стану від перестановки i до перестановки j за одну ітерацію циклу.

Оскільки ми вибираємо m і n рівномірно та незалежно від діапазону [0, N -1], існує N ² можливих результатів, кожен з яких однаково вірогідний.

Особистість

Для N з цих результатів виконується m = n , тому перестановка не змінюється. Отже,

Pr (i → i).

Транспозиції

Решта випадків N ² - N є транспозиціями, тобто два елементи обмінюються своїми позиціями, і тому перестановка змінюється. Припустимо, одна з цих транспозицій обмінює елементи в положеннях x та y . Є два випадки, як це транспонування може бути сформовано алгоритмом: або m = x , n = y або m = y , n = x . Таким чином, ймовірність кожного перенесення становить 2 / N ².

Як це пов'язано з нашими перестановками? Назвемо дві перестановки i і j сусідами тоді і лише тоді, коли існує транспозиція, яка перетворює i на j (і навпаки). Тоді ми можемо зробити висновок:

Pr (i → j)

Матриця переходів

Ми можемо розташувати ймовірності Pr ( ij ) в матриці переходів P ∈ [0,1] N ! × N !. Визначаємо

p ij = Pr ( ij ),

де p ij - запис у i -му рядку та j -го стовпця P . Зауважте, що

Pr ( ij ) = Pr ( ji ),

що означає Р симетрична.

Зараз ключовим моментом є спостереження за тим, що відбувається, коли ми множимо Р на себе. Візьмемо будь-який елемент p (2) ij із P ²:

p (2) ij

Добуток Pr ( ik ) · Pr ( kj ) - це ймовірність того, що починаючи з перестановки i ми переходимо в перестановку k за один крок, а переходимо в перестановку j після іншого наступного кроку. Таким чином, підсумовуючи всі проміжні перестановки k, ми отримуємо загальну ймовірність переходу від i до j за 2 кроки .

Цей аргумент можна поширити і на вищі сили Р . Особливим наслідком є ​​наступне:

p ( N ) ii - це ймовірність повернення до перестановки i після N кроків, якщо припустити, що ми почали з перестановки i .

Приклад

Програємо це з N = 3. У нас уже є нумерація перестановок. Відповідна матриця переходів така:

P

Множення Р з самим собою дає:

P²

Ще одне множення дає:

P³

Будь-який елемент головної діагоналі дає нам шукану ймовірність, що є 15 / +81 або 5 / 27 .

Обговорення

Хоча цей підхід математично обґрунтований і може бути застосований до будь-якого значення N , він не надто практичний у цій формі. Матриця переходів P має N ! ² записів, що стає дуже великим дуже швидко. Навіть для Н = 10 розмір матриці вже перевищує 13 трильйонів записів. Тому наївна реалізація цього алгоритму виявляється нездійсненною.

Однак, у порівнянні з іншими пропозиціями, цей підхід дуже структурований і не вимагає складних висновків, крім з’ясування того, які перестановки є сусідами. Я сподіваюся, що цю структурованість можна використати, щоб знайти набагато простіші обчислення.

Наприклад, можна використати той факт, що всі діагональні елементи будь-якої потужності Р рівні. Припускаючи, що ми можемо легко обчислити слід P N , рішення тоді просто tr ( P N ) / N !. Слід P N дорівнює сумі N- ї степені його власних значень. Отже, якби ми мали ефективний алгоритм для обчислення власних значень P , ми б були встановлені. Однак я не досліджував це далі, ніж обчислення власних значень до N = 5.


Подивившись, це видається єдиною звуковою / правильною відповіддю на всю тему. Вам пощастило узагальнити результат? Я збираюся подивитися сьогодні ввечері.
Глено

@Gleno Я не розглядав це далі того, що я вже писав. Я хотів би почути про ваші знахідки!
Рейма

1
Ну, я ще не встиг попрацювати над проблемою. Я перевірив ваші висновки (вивів ту саму матрицю для n = 3, однакові ймовірності тощо) та обчислив власні значення та ймовірності до N = 7. Очевидно, є закономірність, але вона не вискакувала мені, дивлячись на послідовності власних значень . Я також спробував обдурити, дивлячись на діагональні елементи матриць до n-ї степені, і перевіряючи, чи дотримуються вони жодної відомої послідовності - але, на жаль, вони цього не роблять. Трохи сумно, що ваш підхід, який на цей момент дав імовірність до N = 7, є таким низьким на сторінці.
Глено

4

Легко спостерігати межі 1 / n n <= p <= 1 / n.

Ось неповна ідея показу обернено-експоненціальної верхньої межі.

Ви малюєте числа з {1,2, .., n} 2n разів. Якщо будь-який з них унікальний (трапляється рівно один раз), масив неодмінно буде змінено, оскільки елемент зник і не може повернутися на своє початкове місце.

Імовірність того, що фіксоване число є унікальним, становить 2n * 1 / n * (1-1 / n) ^ (2n-1) = 2 * (1-1 / n) ^ (2n-1), що є асимпотично 2 / e 2 , обмежений від 0. [2n, тому що ви обираєте, на якій спробі ви його отримаєте, 1 / n, що ви отримали його на цій спробі, (1-1 / n) ^ (2n-1), що ви не отримали його на інші спроби]

Якби події були незалежними, ви отримали б шанс, що всі числа неоднозначні, це (2 / e 2 ) ^ n, що означало б p <= O ((2 / e 2 ) ^ n). На жаль, вони не є незалежними. Я вважаю, що межі можна продемонструвати більш складним аналізом. Ключове слово "проблема з кульками та ящиками".


3

Одне спрощене рішення -

p> = 1 / N N

Оскільки один із можливих способів масив залишається незмінним, це якщо m = nдля кожної ітерації. І mдорівнює nможливості 1 / N.

Це, звичайно, вище, ніж це. Питання в тому, на скільки ..

Друга думка: Можна також стверджувати, що якщо випадково перетасувати масив, кожна перестановка має однакову ймовірність. Оскільки є n!перестановки, ймовірність отримати лише одну (ту, яку ми маємо на початку) є

p = 1 / N!

що трохи краще попереднього результату.

Як обговорювалося, алгоритм є упередженим. Це означає, що не кожна перестановка має однакову ймовірність. Тож 1 / N!не зовсім точно. Ви повинні з’ясувати, як відбувається розподіл перестановок.


1
Масив перемішується випадковим чином, питання полягає в тому, чи перемішується він рівномірно. Ці два поняття не пов’язані між собою.
Дітріх Епп

1
@DietrichEpp: так, тоді вам доведеться продемонструвати, чи є цей алгоритм упередженим чи ні. Якщо це не упереджено, воно рівномірно розподіляється.
duedl0r

5
Ах, я щойно згадав надзвичайно простий доказ того, що алгоритм упереджений. Алгоритм може виконуватися N ^ N різними способами, рівномірно, але кількість перестановок N! майже напевно не є дільником N ^ N, отже, алгоритм упереджений для N> = 3.
Дітріх Епп

@DietrichEpp Для доказу, n!який не завжди розділяє n^n, просто розглянемо випадок, коли nпросте число більше за 2.
Денніс Менг,

1
@ duedl0r: Це математичний доказ, тому ви перевіряєте його, вивчаючи логічні кроки та переконуючись, що вони правильно виконуються. Немає необхідності фактично запускати програму, якщо ви вже знаєте, яка відповідь. Як я вже говорив, це не конструктивний доказ, тому доказ не дає вам жодної інформації про те, скільки упередженості існує, він лише доводить, що упередженість ПОВИННА бути, оскільки в іншому випадку могло б бути логічне протиріччя. Коли ви говорите, що "скасовує", це насправді лише здогадка, але ви можете спробувати довести, що воно скасовується.
Дітріх Епп

3

FYI, я не впевнений, що виконується вище (1 / n ^ 2):

N=5 -> 0.019648 < 1/25
N=6 -> 0.005716 < 1/36

Код вибірки:

import random

def sample(times,n):
    count = 0;
    for i in range(times):
        count += p(n)
    return count*1.0/times;

def p(n):
    perm = range(n);
    for i in range(n):
        a = random.randrange(n)
        b = random.randrange(n)

        perm[a],perm[b]=perm[b],perm[a];


    return perm==range(n)

print sample(500000,5)

примітка, ви можете поміняти місцями, пройшовши перм [а], перм [b] = перм [б], перм [а]
Роберт Кінг

3

Усі припускають A[i] == i, що явно не було зазначено. Я також буду робити це припущення, але зверніть увагу, що ймовірність залежить від змісту. Наприклад, якщо A[i]=0, то ймовірність = 1 для всіх N.

Ось як це зробити. Дозвольте P(n,i)імовірність того, що отриманий масив відрізняється рівним i транспозиціям від вихідного масиву.

Ми хочемо знати P(n,0). Це правда, що:

P(n,0) = 
1/n * P(n-1,0) + 1/n^2 * P(n-1,1) = 
1/n * P(n-1,0) + 1/n^2 * (1-1/(n-1)) * P(n-2,0)

Пояснення: ми можемо отримати вихідний масив двома способами, або зробивши "нейтральну" транспозицію в масиві, який вже є добрим, або повернувши єдину "погану" транспозицію. Щоб отримати масив лише з однією «поганою» транспозицією, ми можемо взяти масив з 0 поганими транспозиціями і зробити одну транспозицію, яка не є нейтральною.

РЕДАКТУВАТИ: -2 замість -1 у P (n-1,0)


1
1) У запитанні зазначено "Припустимо, що масив містить унікальні елементи". тож без втрати загальності можна припустити A[i] == i. 2) Я не думаю, що взагалі існує простий спосіб знайти P(n,i). Це легко P(n,0), але для більших iнезрозуміло, скільки транспозицій є "добрими", а скільки "поганими".
sdcvvc

@sdcvvc: Ви говорите, що це легко знайти, P(n,0)але саме в цьому полягає питання. Якщо ви не згодні з цими аргументаціями, наведіть приклад, коли це не вдається, або чому це неправильно.
Леонард Ейлер

Я так не думаю P(n-1,1) = (1-1/(n-1)) * P(n-2,0). Якщо ви знаходитесь посередині, ви можете додати ще один поганий крок, який ви скасуєте пізніше. Наприклад, розглянемо (1234) => (2134) => (2143) => (1243) => (1234). Число n-1 у знаменнику також є підозрілим, оскільки випадкова функція дозволяє повторення.
sdcvvc

1

Це не повноцінне рішення, але це щось принаймні.

Візьміть певний набір свопів, які не мають ефекту. Ми знаємо, що це могло бути так, що його свопи закінчились утворенням петельки різного розміру, використовуючи загальну кількість nсвопів. (Для цілей цього обмін без ефекту можна вважати петлею розміру 1)

Можливо, ми можемо

1) Розбийте їх на групи на основі розмірів петель
2) Обчисліть кількість способів отримати кожну групу.

(Основна проблема полягає в тому , що є тонни різних груп, але я не знаю , як ви на самому справі обчислити це , якщо не брати до уваги різні угруповання.)


1

Цікаве питання.

Я думаю, що відповідь 1 / N, але я не маю жодних доказів. Коли я знайду доказ, я відредагую свою відповідь.

Що я отримав дотепер:

Якщо m == n, масив змінити не будеш. Ймовірність отримати m == n дорівнює 1 / N, оскільки існує N ^ 2 варіанти, і лише N підходить ((i, i) для кожного 0 <= i <= N-1).

Таким чином, ми отримуємо N / N ^ 2 = 1 / N.

Позначимо Pk ймовірність того, що після k ітерацій свопів масив розміром N залишиться незмінним.

P1 = 1 / N. (Як ми бачили нижче)

P2 = (1 / N) P1 + (N-1 / N) (2 / N ^ 2) = 1 / N ^ 2 + 2 (N-1) / N ^ 3.

Explanation for P2:
We want to calculate the probability that after 2 iterations, the array with 
N elements won't change. We have 2 options : 
- in the 2 iteration we got m == n (Probability of 1/N)
- in the 2 iteration we got m != n (Probability of N-1/N)

If m == n, we need that the array will remain after the 1 iteration = P1.
If m != n, we need that in the 1 iteration to choose the same n and m 
(order is not important). So we get 2/N^2.
Because those events are independent we get - P2 = (1/N)*P1 + (N-1/N)*(2/N^2).

Pk = (1 / N) * Pk-1 + (N-1 / N) * X. (перший для m == n, другий для m! = n)

Я повинен більше думати про те, що X дорівнює. (X - це просто заміна реальної формули, а не константа чи щось інше)

Example for N = 2.
All possible swaps:

(1 1 | 1 1),(1 1 | 1 2),(1 1 | 2 1),(1 1 | 2 2),(1 2 | 1 1),(1 2 | 1 2)
(1 2 | 2 1),(1 2 | 2 2),(2 1 | 1 1),(2 1 | 1 2),(2 1 | 2 1),(2 1 | 2 2)
(2 2 | 1 1),(2 2 | 1 2),(2 2 | 2 1),(2 1 | 1 1).

Total = 16. Exactly 8 of them remain the array the same.
Thus, for N = 2, the answer is 1/2.

EDIT: Я хочу представити інший підхід:

Ми можемо класифікувати свопи за трьома групами: конструктивні свопи, деструктивні свопи та нешкідливі свопи.

Конструктивний своп визначається як своп, який призводить до того, що принаймні один елемент переміщується в потрібне місце.

Деструктивний своп визначається як своп, який призводить до переміщення принаймні одного елемента з правильного положення.

Нешкідливий своп визначається як своп, який не належить до інших груп.

Неважко зрозуміти, що це розділ усіх можливих свопів. (перетин = порожній набір).

Тепер претензію, яку я хочу довести:

    The array will remain the same if and only if 
the number of Destructive swap == Constructive swap in the iterations.

Якщо хтось має зустрічний приклад, будь ласка, запишіть його як коментар.

Якщо це твердження вірно, ми можемо взяти всі комбінації та підсумувати їх - 0 нешкідливих свопів, 1 нешкідливий своп, .., N нешкідливих свопів.

І для кожного можливого k нешкідливого обміну ми перевіряємо, чи є парним Nk, якщо ні, пропускаємо. Якщо так, то приймаємо (Nk) / 2 за руйнівну та (Nk) за конструктивну. І просто подивіться на всі можливості.


1
Ваші міркування помилкові, оскільки ми поміняємо місцями N разів, тобто ймовірність буде 1 / N ^ 2. Але це також неправильно через сукупність факторів, деякі з яких, принаймні, вже були пояснені в інших відповідях.
Конрад Рудольф

@KonradRudolph, де ти бачив, я писав, що ймовірність дорівнює 1 / N ^ 2? Я впевнений, що написане мною є правильним.
barak1412

Поясніть чому? (яка частина неправильна) Я майже впевнений, що це не так.
barak1412

Хіба мій перший коментар не пояснює, що не так? Імовірність n = m дорівнює 1 / N для одного обміну. Ви робите це N разів, він повинен бути однаковим кожного разу, що дає 1 / N * 1 / N = 1 / N ^ 2. В основному, розрахунок P2 у вашій відповіді помилковий. Просто інтуїтивно повинно бути очевидно, що шанс зберегти оригінальний масив повинен бути набагато меншим, ніж 1 у Н.
Конрад Рудольф,

Зачекайте, міркування у моєму коментарі вище помилкові, ви не можете помножити ймовірності, оскільки вони умовні, але ваша формула для P2 все ще неправильна, і інтуїція все ще зберігається.
Конрад Рудольф

1

Я б змоделював проблему як мультиграф, де вузли є елементами масиву, а свопи додають ненаправлений (!) Зв’язок між ними. Потім шукайте цикли якось (усі вузли є частиною циклу => оригінал)

Дійсно, потрібно повертатися до роботи! :(


1

ну, з математичної точки зору:

щоб елементи масиву кожного разу мінялися місцями в одному місці, тоді функція Rand (N) повинна генерувати одне і те ж число двічі для int m та int n. тому ймовірність того, що функція Rand (N) генерує одне і те ж число двічі, дорівнює 1 / N. і ми маємо Rand (N), який називається N разів всередині циклу for, тому маємо ймовірність 1 / (N ^ 2)


1

Наївна реалізація в C #. Ідея полягає в тому, щоб створити всі можливі перестановки початкового масиву і перерахувати їх. Тоді ми будуємо матрицю можливих змін стану. Помноживши матрицю на себе N разів, ми отримаємо матрицю, яка показує, скільки існує способів, які ведуть від перестановки #i до перестановки #j за N кроків. Elemet [0,0] покаже, скільки шляхів призведе до того самого початкового стану. Сума елементів рядка # 0 покаже загальну кількість різних способів. Поділивши перше на друге, ми отримуємо ймовірність.

Насправді загальна кількість перестановок дорівнює N ^ (2N).

Output:
For N=1 probability is 1 (1 / 1)
For N=2 probability is 0.5 (8 / 16)
For N=3 probability is 0.1851851851851851851851851852 (135 / 729)
For N=4 probability is 0.068359375 (4480 / 65536)
For N=5 probability is 0.0193664 (189125 / 9765625)
For N=6 probability is 0.0057198259072973293366526105 (12450816 / 2176782336)

class Program
{
    static void Main(string[] args)
    {
        for (int i = 1; i < 7; i++)
        {
            MainClass mc = new MainClass(i);
            mc.Run();
        }
    }
}

class MainClass
{
    int N;
    int M;

    List<int> comb;
    List<int> lastItemIdx;
    public List<List<int>> combinations;
    int[,] matrix;

    public MainClass(int n)
    {
        N = n;

        comb = new List<int>();
        lastItemIdx = new List<int>();
        for (int i = 0; i < n; i++)
        {
            comb.Add(-1);
            lastItemIdx.Add(-1);
        }

        combinations = new List<List<int>>();
    }

    public void Run()
    {
        GenerateAllCombinations();
        GenerateMatrix();
        int[,] m2 = matrix;
        for (int i = 0; i < N - 1; i++)
        {
            m2 = Multiply(m2, matrix);
        }

        decimal same = m2[0, 0];
        decimal total = 0;
        for (int i = 0; i < M; i++)
        {
            total += m2[0, i];
        }

        Console.WriteLine("For N={0} probability is {1} ({2} / {3})", N, same / total, same, total);
    }

    private int[,] Multiply(int[,] m2, int[,] m1)
    {
        int[,] ret = new int[M, M];
        for (int ii = 0; ii < M; ii++)
        {
            for (int jj = 0; jj < M; jj++)
            {
                int sum = 0;

                for (int k = 0; k < M; k++)
                {
                    sum += m2[ii, k] * m1[k, jj];
                }

                ret[ii, jj] = sum;
            }
        }

        return ret;
    }

    private void GenerateMatrix()
    {
        M = combinations.Count;
        matrix = new int[M, M];

        for (int i = 0; i < M; i++)
        {
            matrix[i, i] = N;
            for (int j = i + 1; j < M; j++)
            {
                if (2 == Difference(i, j))
                {
                    matrix[i, j] = 2;
                    matrix[j, i] = 2;
                }
                else
                {
                    matrix[i, j] = 0;
                }
            }
        }
    }

    private int Difference(int x, int y)
    {
        int ret = 0;
        for (int i = 0; i < N; i++)
        {
            if (combinations[x][i] != combinations[y][i])
            {
                ret++;
            }

            if (ret > 2)
            {
                return int.MaxValue;
            }
        }

        return ret;
    }

    private void GenerateAllCombinations()
    {
        int placeAt = 0;
        bool doRun = true;
        while (doRun)
        {
            doRun = false;
            bool created = false;

            for (int i = placeAt; i < N; i++)
            {
                for (int j = lastItemIdx[i] + 1; j < N; j++)
                {
                    lastItemIdx[i] = j; // remember the test

                    if (comb.Contains(j))
                    {
                        continue; // tail items should be nulled && their lastItemIdx set to -1
                    }

                    // success
                    placeAt = i;
                    comb[i] = j;
                    created = true;
                    break;
                }

                if (comb[i] == -1)
                {
                    created = false;
                    break;
                }
            }

            if (created)
            {
                combinations.Add(new List<int>(comb));
            }

            // rollback 
            bool canGenerate = false;
            for (int k = placeAt + 1; k < N; k++)
            {
                lastItemIdx[k] = -1;
            }

            for (int k = placeAt; k >= 0; k--)
            {
                placeAt = k;
                comb[k] = -1;

                if (lastItemIdx[k] == N - 1)
                {
                    lastItemIdx[k] = -1;
                    continue;
                }

                canGenerate = true;
                break;
            }

            doRun = canGenerate;
        }
    }
}

0

Ймовірність того, що m == n на кожній ітерації, то зробіть це N разів. P (m == n) = 1 / N. Тому я думаю, що P = 1 / (n ^ 2) для цього випадку. Але тоді вам слід врахувати значення, які повертаються місцями. Тому я думаю, що відповідь така (текстовий редактор мене отримав) 1 / N ^ N.


1
Це, безумовно, вище ніж (1/N)^N. Справа в тому, що сама по собі є ймовірність того, що масив насправді ніколи не змінюється, ми все ще не підрахували ймовірність того, що речі переміщаються і просто повертаються до початкового стану.
Денніс Менг,

0

Питання: яка ймовірність того, що масив A залишиться незмінним? Умова: Припустимо, що масив містить унікальні елементи.

Спробував рішення на Java.

Випадкове заміщення відбувається на примітивному масиві int. У методі Java параметри завжди передаються за значенням, тому те, що відбувається в методі підкачки, не має значення, оскільки [m] та a [n] елементи масиву (знизу код swap (a [m], a [n])) є передано не повний масив.

Відповідь - масив залишиться незмінним. Незважаючи на згаданий вище стан. Дивіться нижче зразок коду Java:

import java.util.Random;

public class ArrayTrick {

    int a[] = new int[10];
    Random random = new Random();

    public void swap(int i, int j) {
        int temp = i;
        i = j;
        j = temp;
    }

    public void fillArray() {
        System.out.println("Filling array: ");
        for (int index = 0; index < a.length; index++) {
            a[index] = random.nextInt(a.length);
        }
    }

    public void swapArray() {
        System.out.println("Swapping array: ");
        for (int index = 0; index < a.length; index++) {
            int m = random.nextInt(a.length);
            int n = random.nextInt(a.length);
            swap(a[m], a[n]);
        }
    }

    public void printArray() {
        System.out.println("Printing array: ");
        for (int index = 0; index < a.length; index++) {
            System.out.print(" " + a[index]);
        }
        System.out.println();
    }

    public static void main(String[] args) {
        ArrayTrick at = new ArrayTrick();

        at.fillArray();
        at.printArray();
        at.swapArray();
        at.printArray();
    }
}

Вихідні дані:

Масив для заповнення: Масив для друку: 3 1 1 4 9 7 9 5 9 5 Масив для обміну: Масив для друку: 3 1 1 4 9 7 9 5 9 5


1
swap (i, j) не може вплинути ні на що, оскільки цілі числа передаються за значенням
Judge Mental

Ось що я мав на увазі. метод swap () нічого не вплине.
Рашид

Тільки завдяки вашому вибору мови та реалізаціїswap
OrangeDog
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.