Знаходження максимуму XOR двох чисел в інтервалі: чи можемо ми зробити краще, ніж квадратичне?


14

Припустимо, нам дано два числа і і ми хочемо знайти для l \ le i, \, j \ le r .lrmax(ij)li,jr

Наївний алгоритм просто перевіряє всі можливі пари; наприклад, у рубінах у нас буде:

def max_xor(l, r)
  max = 0

  (l..r).each do |i|
    (i..r).each do |j|
      if (i ^ j > max)
        max = i ^ j
      end
    end
  end

  max
end

Я відчуваю, що ми можемо зробити краще, ніж квадратичні. Чи є кращий алгоритм цієї проблеми?


Ви повинні дозволити jпробігатися i+1..rі iпробігати, l...r-1щоб бути точним.
Ахмет Альп Балкан

Відповіді:


20

Ми можемо досягти лінійного виконання в довжині двійкового представлення і :nlr

Префікс у двійковому зображенні та , тобто однаковий для обох значень, також однаковий для всіх значень між ними. Тож ці біти завжди будуть .plr0

Оскільки , біт, що слідує за цим префіксом, буде в і в . Крім того, числа і знаходяться в інтервалі.r>l1r0lp10n|p|1p01n|p|1

Отже, максимум, якого ми шукаємо, дорівнює .0|p|1n|p|


1
Ну, це було просто! Я думаю, я мав би більше роздумувати над цією проблемою.
Jacopo Notarstefano

Нитковий стартер попросив "краще, ніж квадратичний в числах". Це лінійно за розмірами чисел, тому логарифмічно в самих числах.
gnasher729

18

Це можна зробити в час.O(logr)

Максимально можливий XOR будь-яких двох цілих чисел з інтервалу можна визначити з , вважаючи цілими числами. Це значення дорівнює , де - найменше значення, таке, що більше . [l,r]lrl,r2p1p2plr

Ось реалізація в C ++

int maximumXOR(int l, int r) {
    int q = l ^ r, a = 1;
    while(q){
        q /= 2;
        a <<= 1;
    }
    return --a;
}

Чи можете ви пояснити обґрунтування цього алгоритму?
sk1pro99

Це відео може допомогти вам: youtube.com/watch?v=3j-ok4gMjXU
Jack Kinsella

0

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

5 xor 2 = 101 xor 010 перший випадок: біт MSB не встановлений для обох значень у діапазоні. Якщо ми хочемо максимально використовувати це, то нам потрібно зробити це зберегти MSB 5 (100) таким, яким він є, і подумати про максимізація решти нижніх бітів. Як ми знаємо, що нижчі біти всі будуть одним для випадку, коли все 11, це не що інше, як 3, тобто 2 ^ 2-1. Оскільки проблема стосується діапазону від 2 до 5, ми точно маємо 3 у діапазоні. Отже, все, що нам потрібно зробити, - це знайти найвищий набір MSB у більшій із двох значень та додати решту 1 для нижчих бітів.

другий випадок: Що стосується випадку, коли MSB встановлено для обох значень у діапазоні, що виконує xor, безумовно, ці біти встановлені як 0, і нам потрібно повернутися до нижчих бітів. Знову для нижчих бітів нам потрібно повторити ту саму логіку, що і в першому випадку. Приклад: (10, 12) (1010, 1100) Як ви бачите, MSB встановлений як 1, ми повинні повернутися до нижчих бітів, що становить 010 і 100. Тепер ця проблема така ж, як і в першому випадку.

Існує кілька способів цього кодувати. Що я зробив, це зробити просто xor між 'small' і 'high', і це видалить біт MSB, якщо для 'small' і 'high' встановлено біт MSB. Якщо це не так, то це збереже біт MSB. Після цього я намагаюся зробити всі нижчі біти 1, дізнавшись максимальну потужність 2 у виведеному виведенні та віднімаючи з 1.

def range_xor_max(small, high):
  if small == high:
    return 0
  xor = small ^ high
  #how many power of 2 is present
  how_many_power_of_2 = math.log(xor, 2)
  #we need to make all one's below the highest set bit
  return 2**int(math.floor(how_many_power_of_2)+1) - 1

0

Ну, ви можете використовувати XOR l і r, щоб знайти відповідь.

Припустимо, l = 4 і r = 6.

l = 100, r = 110 (двійкові еквіваленти цих чисел)

l⊕r = 0 10

Це означає, що максимальне значення, яке ви шукаєте, неодмінно матиме свій перший біт (MSB) як нульове. (Подумайте над тим, чи можливо для вашого максимального значення 1 натомість замість нього? Якби це було 01010 та 00101, xor був би = 01 111 1 в їх другий біт зліва, це не можливо , щоб отримати 1 до другого біта зліва , тобто в перший біт ліворуч)

Отже, вам залишається решта 2 біта, щоб знайти максимум. Ми знаємо, що максимально можливе значення, коли у нас є n біт = 2 n −1, тому відповідь у цьому випадку буде 2 2 -1 = 4-1 = 3.

З наведеного вище прикладу ми можемо скласти загальний алгоритм для цього.

Крок 1. num = кількість бітів, необхідних для представлення max ( l , r )

Крок 2. res = lr

Крок 3. pos = Позиція першого біта, встановленого зліва в Res (0-індексація на основі)

Крок 4. п = піт - поз

Крок 5. ans = 2 n −1

Часова складність = O (n)


-1

Для кожної двійкової цифри передбачено 4 можливості: 1_and_1, 1_and_0, 0_and_1 або 0_and_0. Можливі нижчі цифри не мають жодної різниці або не змінюють журнал для виведення xor вибору наступної цифри. Найкращий можливий алгоритм - ігнорувати всі нижчі цифри і лише враховувати наступні 2 доступні, враховуючи попередній вибір щодо більш високих цифр. Якщо це 1_and_1 або 0_and_0, вибір зрозумілий, але якщо ця цифра 1_and_0 vs 0_and_1 (які мають однакове значення xor, але неоднакове), то рекурсивно вона повинна дорівнювати алгоритму https://en.wikipedia.org/wiki/Edit_distance , що означає найгірший випадок колоди.


1
Я не впевнений, що ви маєте на увазі під "нижньою цифрою", "логотипом-малим" або "це ... що означає найгірший випадок журналу в квадраті". Не могли б ви уточнити?
Девід Річербі

-1

Протягом 32-бітових інтервалів я просто натрапив на це O(1)рішення в редакціях Hacker Rank. Я поняття не маю, як це працює, але воно працює. (Можливо, хтось може пояснити, чому це працює.)

def max_xor(L,R):
  v = L^R
  v |= v >> 1
  v |= v >> 2
  v |= v >> 4
  v |= v >> 8
  v |= v >> 16
  return b

Джерело: https://www.hackerrank.com/challenges/maximizing-xor/editorial


2
Чим ваша відповідь (після виправлення) відрізняється від ysb.4 (крім того, він пояснив, що відбувається)? Що означає "return b" з незадекларованим "b"? І вибачте, але я не можу отримати доступ до наданого вами посилання.
Зло
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.