Випадкові елементи масиву без повторень, elwood - s blog

Іноді буває потрібно вирішити таке завдання: є масив, з якого ми по черзі вибираємо рандомний елементи. І потрібно зробити так, щоб одного разу вибрані елементи більше нам не траплялися. Очевидне рішення в лоб - завести поруч Set, в якому зберігати або самі вибрані елементи, або їх ідентифікатори - зовсім не годиться: мало того, що доведеться використовувати додаткову пам'ять, так ще й немає гарантії, що наступний елемент вийде знайти відразу ж. Чим більше ми будемо вибирати елементів, тим довше ми будемо змушені шукати наступний рандомний елемент, який ще відсутній в безлічі використаних. Інший спосіб - перекладати використані елементи в іншу колекцію - працездатний тільки якщо вихідна колекція допускає операцію remove, і вона реалізована в ній ефективно. Тому для масивів не підходить (remove просто немає), та й для ArrayList'ов теж не годиться (remove неефективний). Ось з LinkedList буде працювати цілком собі непогано. Бентежить тільки неможливість відновити початковий стан колекції після завершення роботи алгоритму. Тоді вже простіше скопіювати вихідну колекцію цілком, і видаляти з неї елементи. Але це не дуже, якщо колекція велика, а елементів нам потрібно всього з десяток.

Загалом, скористаємося солдатської кмітливістю і зробимо наступний алгоритм: кожен черговий обираний елемент ми міняємо з останнім елементом масиву, і зменшуємо довжину використовуваної частини масиву на одиницю. В кінці масиву таким чином накопичуються "використані" елементи. А щоб зберегти можливість повернутися до вихідного стану, поруч в ArrayList будемо записувати оригінальні індекси використаних елементів.

Випадкові елементи масиву без повторень, elwood - s blog

Випадкові елементи масиву без повторень, elwood - s blog

Випадкові елементи масиву без повторень, elwood - s blog

Власне, я написав клас, який реалізує цю ідею, і, знаходячи його корисним, привожу код.

Схожі статті